【发布时间】:2017-11-12 19:51:29
【问题描述】:
我正在使用最近在 Google I/O 上宣布的 Android 架构组件中的 Android 房间持久性库。事情似乎正常,但我收到以下错误:
警告:tagId 列引用了一个外键,但它不是 指数。这可能会在父表位于任何时候触发全表扫描 已修改,因此强烈建议您创建一个涵盖此内容的索引 列。
我的数据库有 3 个表:Note、Tag 和 JoinNotesTags。 Notes to Tags 是多对多关系,因此使用 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`)"
所以,我的问题是:这个警告只是(仍然是 alpha-release)房间库中的一个错误——即编译时分析缺少 tagId 是这个复合索引的一部分这一事实吗?还是我真的有需要解决的索引问题以避免全表扫描?
【问题讨论】:
-
我们需要查看您的 table 定义,而不是您的 Java 代码。具体来说,我认为错误不是
tagId列没有索引,而是它引用了一个没有索引的外键。 -
@TimBiegeleisen,已更新问题以包含
JoinNotesTags的表定义。但为了记录,Tag.id是一个主键。此外,警告说问题出在tagId列上——而不是它引用的父表中的列 (Tag.id)。
标签: android sqlite android-sqlite android-room