Estoy intentando crear un índice en SQLite3
(3.18) usando json_extract
expresiones. Mi objetivo es ejecutar consultas que solo requieren que el índice produzca resultados. La razón de esto es que json_extract
es una operación costosa que obstaculizaría el rendimiento cuando se opera en conjuntos de datos y / o valores más grandes. Llegué a la conclusión de que necesito un índice de cobertura para satisfacer mis necesidades.
Paso 1: prueba de la teoría utilizando una estructura de tabla 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
Rendimientos
SCAN TABLE Player USING COVERING INDEX Player_FirstName
Esto es exactamente lo que espero. El planificador de consultas calculó que el Player_FirstName
índice es apropiado debido a la ORDER BY
cláusula, y dado que la WHERE
declaración opera solo en un valor que también está en ese índice, no necesita leer la tabla. Finalmente, la SELECT
declaración incluye solo las columnas indexadas, lo que resulta en una consulta que no toca la tabla en absoluto .
Paso 2: prueba de la teoría con una expresión de extracto
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
Rendimientos
SCAN TABLE PlayerJ USING INDEX PlayerJ_FirstName
Esto no es lo que esperaba. El planificador de consultas parece haber descubierto que la ORDER BY
cláusula está JSON_EXTRACT(Data, '$.FirstName')
activada y, por lo tanto, parece haber seleccionado el índice apropiado. Pero ahí es donde mi razonamiento termina abruptamente. ¿Que esta pasando aqui? Hubiera esperado que el planificador de consultas descubriera que esto es lo mismo que la prueba anterior, y el índice se usaría como índice de cobertura. Pero no lo hace.
Por qué no? ¿Y cómo se puede modificar esta segunda prueba para que solo se ejecute contra el índice?