我正在尝试SQLite3
使用json_extract
表达式在(3.18)中创建索引。我的目标是执行只需要索引即可产生结果的查询。这样做的原因是json_extract
操作昂贵,在较大的数据集和/或值上进行操作时会降低性能。我得出结论,我需要一个覆盖指数来满足我的需求。
步骤1-使用标准表结构测试理论
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
产量
SCAN TABLE Player USING COVERING INDEX Player_FirstName
这正是我所期望的。查询计划人员认为,Player_FirstName
由于该ORDER BY
子句,索引是适当的,并且由于该WHERE
语句仅对也在该索引中的值进行操作,因此不需要读取表。最后,SELECT
声明只包括因此导致在不触及表的查询索引列在所有。
第2步-使用提取表达式测试理论
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
产量
SCAN TABLE PlayerJ USING INDEX PlayerJ_FirstName
这不是我所期望的。查询计划者似乎已经发现该ORDER BY
子句on JSON_EXTRACT(Data, '$.FirstName')
,因此似乎已选择了适当的索引。但这就是我的推理突然结束的地方。这里发生了什么?我本以为查询计划者会发现这与以前的测试相同,并且该索引将用作覆盖索引。但事实并非如此。
为什么不?以及如何修改第二项测试,使其仅针对索引运行?