Android 关于外键中不属于索引的列的 Room 编译时警告。这是什么意思?

Android Room compile-time warning about column in foreign key not part of an index. What does it mean?

我正在使用最近在 Google I/O 上宣布的 Android 架构组件中的 Android 房间持久性库。一切似乎正常,但我收到以下错误:

Warning:tagId column references a foreign key but it is not part of an index. This may trigger full table scans whenever parent table is modified so you are highly advised to create an index that covers this column.

我的数据库有 3 个 table:NoteTagJoinNotesTags。 Notes to Tags 是多对多关系,因此 JoinNotesTags table 来处理映射。 table 很简单:

外键约束在 JoinNotesTags table 上定义。作为参考,这里是 JoinNotesTags table:

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 
)"

这是 class 对应的 @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 注释中看到的那样,tagId noteId 一起包含在复合唯一索引中。我已经确认在自动生成的 json 模式文件中也正确定义了该索引:

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

所以,我的问题是:此警告是否只是(仍处于 alpha 版本)Room Library 中的错误——即编译时分析遗漏了 tagId 是此组合的一部分这一事实指数?还是我真的有需要解决的索引问题以避免完整 table 扫描?

当您修改 Tag table 时,数据库可能需要在 JoinNotesTags table 中查找相应的行。为了提高效率,requires an indextagId 列。

您的复合索引对此没有用;由于 way how indexes work,要搜索的列必须是索引中最左边的列。

您应该只在 tagId 列上添加索引。 (你可以交换复合索引中列的顺序,但是你会遇到与 noteId 相同的问题。)

您需要为列添加索引以加快查询速度 这是一个例子

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

在 kotlin 代码中:

之前

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

之后

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

如果即使正确定义了索引也会出现此错误,则可能存在除此错误之外的其他编译错误。要修复它,只需注释在关系 table 中定义外键的代码,然后创建项目,修复其他编译错误并取消注释给定代码。