web-dev-qa-db-ja.com

Androidインデックスの一部ではない外部キーの列に関するルームコンパイル時の警告。それはどういう意味ですか?

Google I/Oで最近発表されたAndroid Architecture ComponentsからAndroidのRoom Persistence Libraryを使用しています。物事は機能しているようですが、次のエラーが表示されます。

警告:tagId列は外部キーを参照していますが、インデックスの一部ではありません。これにより、親テーブルが変更されるたびに全テーブルスキャンがトリガーされる可能性があるため、この列をカバーするインデックスを作成することを強くお勧めします。

データベースには、NoteTagJoinNotesTagsの3つのテーブルがあります。タグへのメモは多対多の関係であるため、マッピングを処理するJoinNotesTagsテーブルです。テーブルは簡単です。

  • Note.idTag.idは両方とも主キーです
  • JoinNotesTags.noteId参照Note.id
  • JoinNotesTags.tagId参照Tag.id

外部キー制約は、JoinNotesTagsテーブルで定義されます。参考のために、JoinNotesTagsテーブルのCREATE TABLEステートメントを以下に示します。

"CREATE TABLE IF NOT EXISTS `JoinNotesTags` (
    `id` INTEGER PRIMARY KEY AUTOINCREMENT, 
    `noteId` INTEGER, 
    `tagId` INTEGER, 
    FOREIGN KEY(`noteId`) REFERENCES `Note`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , 
    FOREIGN KEY(`tagId`) REFERENCES `Tag`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION 
)"

そして、そのクラスに対応する@Entityアノテーションは次のとおりです。

@Entity(
        indices = arrayOf(Index(value = *arrayOf("noteId", "tagId"), unique = true)),
        foreignKeys = arrayOf(
                ForeignKey(
                        entity = Note::class,
                        parentColumns = arrayOf("id"),
                        childColumns = arrayOf("noteId"),
                        onDelete = ForeignKey.CASCADE),
                ForeignKey(
                        entity = Tag::class,
                        parentColumns = arrayOf("id"),
                        childColumns = arrayOf("tagId"))
        )
)

@Entityアノテーションからわかるように、tagIdisは、noteIdとともに複合一意インデックスに含まれています。このインデックスは、自動生成されたjsonスキーマファイルでも正しく定義されていることを確認しました。

"CREATE UNIQUE INDEX `index_JoinNotesTags_noteId_tagId` 
    ON `JoinNotesTags` (`noteId`, `tagId`)"

だから、私の質問:この警告は(まだアルファリリースの)ルームライブラリのバグですか?つまり、コンパイル時の分析では、tagIdがこの複合インデックスの一部であるという事実が欠落していますか?または、テーブル全体のスキャンを回避するために解決する必要があるインデックス作成の問題が本当にありますか?

29
mikejonesguy

Tagテーブルを変更すると、データベースはJoinNotesTagsテーブル内の対応する行を検索する必要がある場合があります。効率的にするために、これはtagId列の インデックスが必要 です。

複合インデックスはそのためには役立ちません。 インデックスの動作方法 のため、検索する列はインデックスの左端の列でなければなりません。

tagId列のみにインデックスを追加する必要があります。 (複合インデックスの列の順序を入れ替えることはできますが、noteIdでも同じ問題が発生します。)

14
CL.

クエリを高速化するには、列にインデックスを追加する必要があります

@Entity(indices = {@Index("artist_id")})
public class Artist{
    @NonNull
    @PrimaryKey
    @ColumnInfo(name = "artist_id")
    public String id;
    public String name;
}
37
Prakash

kotlinコードの場合:

@Expose
@SerializedName("question_id")
@ColumnInfo(name = "question_id")
var questionId: Long

@Expose
    @SerializedName("question_id")
    @ColumnInfo(name = "question_id", index = true) //just add index = true
    var questionId: Long
18
arjava