Ich versuche, in SQLite3
(3.18) einen Index mit json_extract
Ausdrücken zu erstellen . Mein Ziel ist es, Abfragen auszuführen, für die nur der Index erforderlich ist, um Ergebnisse zu erzielen. Der Grund dafür ist, dass json_extract
es sich um einen teuren Vorgang handelt, der die Leistung beim Betrieb mit größeren Datenmengen und / oder Werten beeinträchtigen würde. Ich kam zu dem Schluss, dass ich einen Deckungsindex brauche, der meinen Bedürfnissen entspricht.
Schritt 1 - Testen der Theorie unter Verwendung einer normalen Tabellenstruktur
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
Erträge
SCAN TABLE Player USING COVERING INDEX Player_FirstName
Genau das erwarte ich. Der Abfrageplaner stellte fest, dass der Player_FirstName
Index aufgrund der ORDER BY
Klausel angemessen ist. Da die WHERE
Anweisung nur mit einem Wert arbeitet, der sich auch in diesem Index befindet, muss die Tabelle nicht gelesen werden. Schließlich ist die SELECT
enthält Anweisung nur die indizierten Spalten daher in einer Abfrage führt , dass die Tabelle nicht berühren überhaupt .
Schritt 2 - Testen der Theorie mit einem Extraktausdruck
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
Erträge
SCAN TABLE PlayerJ USING INDEX PlayerJ_FirstName
Das ist nicht , was ich erwartet hatte. Der Abfrageplaner scheint herausgefunden zu haben, dass die ORDER BY
Klausel aktiviert ist JSON_EXTRACT(Data, '$.FirstName')
, und scheint daher den entsprechenden Index ausgewählt zu haben. Aber hier endet meine Argumentation abrupt. Was geht hier vor sich? Ich hätte erwartet, dass der Abfrageplaner herausfindet, dass dies derselbe wie der vorherige Test ist und der Index als Deckungsindex verwendet wird. Aber das tut es nicht.
Warum nicht? Und wie kann dieser zweite Test so geändert werden, dass er nur für den Index ausgeführt wird?