我最近在使用Google I/O上宣布的Android Architecture组件中的Android Room持久性库。似乎一切工作正常,但是我遇到了以下错误:
警告:tagId列引用外键,但它不是索引的一部分。每当修改父表时,这可能会触发完整的表扫描,因此强烈建议您创建覆盖此列的索引。
我的数据库有3个表:Note
、Tag
和JoinNotesTags
。笔记与标签之间是多对多关系,因此需要使用JoinNotesTags表来处理映射关系。这些表很简单:
Note.id
和Tag.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
注释中可以看到的那样,tagId
与noteId
一起包含在复合唯一索引中。 我已确认这个索引在自动生成的JSON模式文件中正确定义:
"CREATE UNIQUE INDEX `index_JoinNotesTags_noteId_tagId`
ON `JoinNotesTags` (`noteId`, `tagId`)"
所以我的问题是:这个警告只是 Room Library(仍处于 alpha 版本)中的一个 bug 吗 —— 也就是说,编译时分析没有注意到 tagId
是这个复合索引的一部分吗?还是我真的有一个需要解决的索引问题,以避免全表扫描?
tagId
列没有索引,而是它引用了一个未建立索引的外键。 - Tim BiegeleisenJoinNotesTags
表的定义。但是为了记录,Tag.id
是主键。此外,警告显示问题出在tagId
列上,而不是它所引用的父表中的列(Tag.id
)。 - mikejonesguy