53

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

警告:tagId 列引用了外键,但它不是索引的一部分。每当修改父表时,这可能会触发全表扫描,因此强烈建议您创建覆盖该列的索引。

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

  • Note.id并且Tag.id都是主键
  • JoinNotesTags.noteId参考Note.id
  • JoinNotesTags.tagId参考Tag.id

外键约束是在JoinNotesTags表上定义的。作为参考,这里是表的CREATE TABLE语句JoinNotesTags

"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注释中可以看出,tagId 一起包含在复合唯一索引中noteId。我已经确认在自动生成的 json 模式文件中也正确定义了这个索引:

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

所以,我的问题是:这个警告只是(仍然是 alpha 版本的)房间库中的一个错误——即编译时分析缺少tagId这个复合索引的一部分的事实吗?还是我真的有一个索引问题需要解决以避免全表扫描?

4

4 回答 4

78

在 kotlin 代码中:

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

@ColumnInfo(name = "question_id", index = true) //just add index = true
var questionId: Long
于 2019-01-23T03:25:09.950 回答
52

您需要为列添加索引以获得更快的查询这是一个示例

@Entity(indices = {@Index("artist_id")})
public class Artist{
    @NonNull
    @PrimaryKey
    @ColumnInfo(name = "artist_id")
    public String id;
    public String name;
}
于 2018-05-15T17:32:14.200 回答
23

当您修改Tag表时,数据库可能需要在JoinNotesTags表中查找相应的行。为了提高效率,这需要列上的索引tagId

您的复合索引对此没有用;由于索引的工作方式,要搜索的列必须是索引中最左边的列。

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

于 2017-06-11T07:16:35.167 回答
0

如果即使正确定义了索引也会出现此错误,那么除了这个之外还有其他一些编译错误。要修复它,只需注释在关系表中定义外键的代码,并制作项目,并修复其他编译错误并取消注释给定的代码。

于 2020-01-15T14:49:48.947 回答