Sto tentando di creare un indice in SQLite3(3.18) usando le json_extractespressioni. 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_FirstNameindice è appropriato a causa della ORDER BYclausola e poiché l' WHEREistruzione opera solo su un valore che si trova anche in quell'indice, non è necessario leggere la tabella. Infine, l' SELECTistruzione 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 BYclausola è 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?