Я пытаюсь создать индекс в SQLite3
(3.18), используя json_extract
выражения. Моя цель состоит в том, чтобы выполнять запросы, которые требуют только индекса для получения результатов. Причина этого заключается в том, что json_extract
это дорогостоящая операция, которая может снизить производительность при работе с большими наборами данных и / или значениями. Я пришел к выводу, что мне нужен индекс покрытия, чтобы удовлетворить мои потребности.
Шаг 1 - Проверка теории с использованием нормальной структуры таблицы
CREATE TABLE Player (
Id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
FirstName TEXT NOT NULL,
MiddleName TEXT,
LastName TEXT NOT NULL
);
CREATE INDEX Player_FirstName ON Player (
FirstName ASC,
LastName ASC
);
EXPLAIN QUERY PLAN SELECT
FirstName, LastName
FROM
Player
WHERE
LENGTH(LastName) > 10
ORDER BY
FirstName
LIMIT
10
OFFSET
0
Урожайность
SCAN TABLE Player USING COVERING INDEX Player_FirstName
Это именно то, что я ожидаю. Планировщик запросов выяснил, что Player_FirstName
индекс является подходящим из-за ORDER BY
предложения, и поскольку WHERE
оператор работает только со значением, которое также содержится в этом индексе, ему не нужно читать таблицу. Наконец, SELECT
оператор включает только индексированные столбцы поэтому полученные в запросе, не задевает таблицу на всех .
Шаг 2 - Проверка теории с помощью выражения выдержки
CREATE TABLE PlayerJ (
Id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
Data TEXT NOT NULL
);
CREATE INDEX PlayerJ_FirstName ON PlayerJ (
JSON_EXTRACT(Data, '$.FirstName') ASC,
JSON_EXTRACT(Data, '$.LastName') ASC
);
EXPLAIN QUERY PLAN SELECT
JSON_EXTRACT(Data, '$.FirstName') AS FirstName,
JSON_EXTRACT(Data, '$.LastName') AS LastName
FROM
PlayerJ
WHERE
LENGTH(LastName) > 10
ORDER BY
FirstName
LIMIT
10
OFFSET
0
Урожайность
SCAN TABLE PlayerJ USING INDEX PlayerJ_FirstName
Это не то, что я ожидал. Планировщик запросов, похоже, выяснил, что ORDER BY
предложение включено JSON_EXTRACT(Data, '$.FirstName')
, и, таким образом, выбрал соответствующий индекс. Но на этом мои рассуждения внезапно заканчиваются. Что здесь происходит? Я ожидал, что планировщик запросов выяснит, что это то же самое, что и предыдущий тест, и индекс будет использоваться в качестве покрывающего индекса. Но это не так.
Почему бы нет? И как можно изменить этот второй тест, чтобы он работал только с индексом?