Estou tentando criar um índice em SQLite3
(3.18) usando json_extract
expressões. Meu objetivo é executar consultas que exigem apenas que o índice produza resultados. A razão para isso é que json_extract
é uma operação cara que prejudicaria o desempenho ao operar com conjuntos de dados e / ou valores maiores. Concluí que preciso de um índice de cobertura para atender às minhas necessidades.
Etapa 1 - Testando a teoria usando uma estrutura de tabela normal
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
Rendimentos
SCAN TABLE Player USING COVERING INDEX Player_FirstName
É exatamente o que eu espero. O planejador de consultas concluiu que o Player_FirstName
índice é apropriado devido à ORDER BY
cláusula e, como a WHERE
instrução opera apenas em um valor que também está nesse índice, ela não precisa ler a tabela. Finalmente, a SELECT
declaração inclui apenas as colunas indexadas, portanto, resultando em uma consulta que não toca a mesa em tudo .
Etapa 2 - Testando a teoria com uma expressão de extrato
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
Rendimentos
SCAN TABLE PlayerJ USING INDEX PlayerJ_FirstName
Isso é não o que eu esperava. O planejador de consultas parece ter descoberto que a ORDER BY
cláusula está JSON_EXTRACT(Data, '$.FirstName')
ativada e, portanto, parece ter selecionado o índice apropriado. Mas é aí que meu raciocínio termina abruptamente. O que está acontecendo aqui? Eu esperava que o planejador de consultas descobrisse que isso é igual ao teste anterior e o índice seria usado como um índice de cobertura. Mas isso não acontece.
Por que não? E como esse segundo teste pode ser modificado para que seja executado apenas no índice?