Dea*_*ike 8 sqlite index optimization execution-plan
我正在尝试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
Run Code Online (Sandbox Code Playgroud)
产量
SCAN TABLE Player USING COVERING INDEX Player_FirstName
Run Code Online (Sandbox Code Playgroud)
这正是我所期望的。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
Run Code Online (Sandbox Code Playgroud)
产量
SCAN TABLE PlayerJ USING INDEX PlayerJ_FirstName
Run Code Online (Sandbox Code Playgroud)
这不是我所期望的。查询规划器似乎已经发现该ORDER BY子句在 上JSON_EXTRACT(Data, '$.FirstName'),因此似乎已经选择了适当的索引。但这就是我的推理突然结束的地方。这里发生了什么?我本来希望查询计划器能够弄清楚这与之前的测试相同,并且该索引将用作覆盖索引。但事实并非如此。
为什么不?以及如何修改第二个测试以使其仅针对索引运行?