Sto tentando di creare un indice in SQLite3
(3.18) usando le json_extract
espressioni. Il mio obiettivo è quello di eseguire query che richiedono solo l'indice per produrre risultati. La ragione di ciò è che json_extract
è un'operazione costosa che ostacolerebbe le prestazioni quando si opera su set di dati e / o valori più grandi. Ho concluso che ho bisogno di un indice di copertura per soddisfare le mie esigenze.
Passaggio 1: test della teoria utilizzando una normale struttura della tabella
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
I rendimenti
SCAN TABLE Player USING COVERING INDEX Player_FirstName
Questo è esattamente quello che mi aspetto. Il pianificatore di query ha calcolato che l' Player_FirstName
indice è appropriato a causa della ORDER BY
clausola e poiché l' WHERE
istruzione opera solo su un valore che si trova anche in quell'indice, non è necessario leggere la tabella. Infine, l' SELECT
istruzione include solo le colonne indicizzate ne consegue una query che non tocca il tavolo affatto .
Passaggio 2: test della teoria con un'espressione extract
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
I rendimenti
SCAN TABLE PlayerJ USING INDEX PlayerJ_FirstName
Questo non è quello che mi aspettavo. Il pianificatore di query sembra aver capito che la ORDER BY
clausola è attiva JSON_EXTRACT(Data, '$.FirstName')
e quindi sembra aver selezionato l'indice appropriato. Ma è qui che il mio ragionamento si interrompe bruscamente. Cosa sta succedendo qui? Mi sarei aspettato che il pianificatore di query potesse capire che era lo stesso del test precedente e che l'indice sarebbe stato usato come indice di copertura. Ma non lo fa.
Perchè no? E come può essere modificato questo secondo test in modo che venga eseguito solo sull'indice?