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:Note
、Tag
和 JoinNotesTags
。 Notes to Tags 是多对多关系,因此 JoinNotesTags table 来处理映射。 table 很简单:
Note.id
和Tag.id
都是主键
JoinNotesTags.noteId
引用 Note.id
JoinNotesTags.tagId
引用 Tag.id
外键约束在 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 index 在 tagId
列。
您的复合索引对此没有用;由于 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 中定义外键的代码,然后创建项目,修复其他编译错误并取消注释给定代码。
我正在使用最近在 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:Note
、Tag
和 JoinNotesTags
。 Notes to Tags 是多对多关系,因此 JoinNotesTags table 来处理映射。 table 很简单:
Note.id
和Tag.id
都是主键JoinNotesTags.noteId
引用Note.id
JoinNotesTags.tagId
引用Tag.id
外键约束在 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 index 在 tagId
列。
您的复合索引对此没有用;由于 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 中定义外键的代码,然后创建项目,修复其他编译错误并取消注释给定代码。