J'essaie de créer un index en SQLite3
(3.18) en utilisant des json_extract
expressions. Mon objectif est d'exécuter des requêtes qui ne nécessitent que l'index pour produire des résultats. La raison en est qu'il json_extract
s'agit d'une opération coûteuse qui entraverait les performances lors de l'utilisation sur des ensembles de données et / ou des valeurs plus importants. J'ai conclu que j'avais besoin d'un indice de couverture adapté à mes besoins.
Étape 1 - Tester la théorie en utilisant une structure de table normale
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
Rendements
SCAN TABLE Player USING COVERING INDEX Player_FirstName
C'est exactement ce que j'attends. Le planificateur de requêtes a supposé que l' Player_FirstName
index est approprié en raison de la ORDER BY
clause, et puisque l' WHERE
instruction ne fonctionne que sur une valeur qui se trouve également dans cet index, il n'a pas besoin de lire la table. Enfin, l' SELECT
instruction inclut uniquement les colonnes indexées, ce qui entraîne une requête qui ne touche pas du tout à la table .
Étape 2 - Tester la théorie avec une expression d'extrait
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
Rendements
SCAN TABLE PlayerJ USING INDEX PlayerJ_FirstName
Ce n'est pas ce à quoi je m'attendais. Le planificateur de requêtes semble avoir compris que la ORDER BY
clause est JSON_EXTRACT(Data, '$.FirstName')
activée et semble donc avoir sélectionné l'index approprié. Mais c'est là que mon raisonnement se termine brusquement. Qu'est-ce qui se passe ici? Je m'attendais à ce que le planificateur de requêtes découvre que c'est la même chose que le test précédent, et que l'index serait utilisé comme index de couverture. Mais ce n'est pas le cas.
Pourquoi pas? Et comment modifier ce deuxième test pour qu'il ne s'exécute que contre l'index?