#android #database #sqlite #kotlin #android-room
#Android #sqlite #android-sqlite #android-room
Вопрос:
Я использую библиотеку персистентности Android Room из компонентов архитектуры Android, недавно анонсированных в Google I / O. Кажется, все работает, но я получаю следующую ошибку:
Предупреждение: столбец TagID ссылается на внешний ключ, но он не является частью индекса. Это может вызвать полное сканирование таблицы при каждом изменении родительской таблицы, поэтому настоятельно рекомендуется создать индекс, который охватывает этот столбец.
В моей базе данных есть 3 таблицы: Note
, Tag
и JoinNotesTags
. Примечания к тегам — это отношение «многие ко многим», отсюда таблица 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`)"
Итак, мой вопрос: является ли это предупреждение просто ошибкой в библиотеке Room (все еще альфа-версии) — т.Е. в анализе во время компиляции отсутствует тот факт, что tagId
является частью этого составного индекса? Или у меня действительно проблема с индексацией, которую мне нужно решить, чтобы избежать полного сканирования таблицы?
Комментарии:
1. Нам нужно увидеть определения вашей таблицы , а не ваш Java-код. В частности, я считаю, что ошибка заключается не в том, что у
tagId
столбца нет индекса, а в том, что он ссылается на внешний ключ, который не индексируется.2. @TimBiegeleisen, вопрос обновлен, чтобы включить определение таблицы для
JoinNotesTags
. Но для справки,Tag.id
это первичный ключ. Кроме того, в предупреждении говорится, что проблема связана соtagId
столбцом, а не со столбцом в родительской таблице, на который он ссылается (Tag.id
).
Ответ №1:
Когда в коде kotlin:
Перед
@ColumnInfo(name = "question_id")
var questionId: Long
После
@ColumnInfo(name = "question_id", index = true) //just add index = true
var questionId: Long
Комментарии:
1. У меня это сработало. Ответ можно упростить для удобства чтения, указав только до и после
@ColumnInfo
строки. Остальные, особенно модифицированные@Expose
и@SerializedName
, не имеют значения и в большинстве случаев не будут использоваться в объектах БД.
Ответ №2:
Вам нужно добавить индекс к столбцам для ускорения запросов, Вот пример
@Entity(indices = {@Index("artist_id")})
public class Artist{
@NonNull
@PrimaryKey
@ColumnInfo(name = "artist_id")
public String id;
public String name;
}
Ответ №3:
При изменении Tag
таблицы базе данных может потребоваться выполнить поиск соответствующих строк в JoinNotesTags
таблице. Для эффективности этого требуется индекс для tagId
столбца.
Ваш составной индекс бесполезен для этого; из-за способа работы индексов, столбец (ы), по которому (которым) выполняется поиск, должен быть крайним левым столбцом (ами) в индексе.
Вы должны добавить индекс только для tagId
столбца. (Вы могли бы поменять порядок столбцов в составном индексе, но тогда у вас возникла бы та же проблема с noteId
.)
Комментарии:
1. Можете ли вы добавить пример иллюстрации
2. Процитирую вас:
You should add an index on only the tagId column
. Означает ли это, что NoteID и TagID должны быть отдельными индексами.?3. @AshishKrishnan Да, оба должны быть крайними левыми столбцами в индексе.
4. Попался!. Спасибо.
Ответ №4:
Если эта ошибка возникает, даже если индекс определен правильно, значит, имеет место какая-то другая ошибка компиляции, отличная от этой. Чтобы исправить это, просто прокомментируйте код, который определяет внешние ключи в таблице отношений, и создайте project , а также исправьте другие ошибки компиляции и раскомментируйте данный код.