我们正在使用sqlite 3.16.0版。
我想创建一些视图以简化我在架构上执行的一些常见的递归操作。但是,与直接运行SQL相比,这些视图要慢得多。
具体来说,该视图向我显示给定节点的祖先:
CREATE VIEW ancestors AS
WITH RECURSIVE ancestors
(
leafid
, parentid
, name
, depth
)
AS
(SELECT id
, parentid
, name
, 1
FROM objects
UNION ALL
SELECT a.leafid
, f.parentid
, f.name
, a.depth + 1
FROM objects f
JOIN ancestors a
ON f.id = a.parentid
) ;
与此查询一起使用时:
SELECT *
FROM ancestors
WHERE leafid = 157609;
产生以下结果:
sele order from deta
---- ------------- ---- ----
2 0 0 SCAN TABLE objects
3 0 1 SCAN TABLE ancestors AS a
3 1 0 SEARCH TABLE objects AS f USING INTEGER PRIMARY KEY (rowid=?)
1 0 0 COMPOUND SUBQUERIES 0 AND 0 (UNION ALL)
0 0 0 SCAN SUBQUERY 1
Run Time: real 0.374 user 0.372461 sys 0.001483
但是直接运行查询(对同一行的初始查询具有WHERE约束),会产生:
WITH RECURSIVE ancestors
(
leafid, parentid, name, depth
)
AS
(SELECT id, parentid , name, 1
FROM objects
WHERE id = 157609
UNION ALL
SELECT a.leafid, f.parentid , f.name, a.depth + 1
FROM objects f
JOIN ancestors a
ON f.id = a.parentid
)
SELECT *
FROM ancestors;
Run Time: real 0.021 user 0.000249 sys 0.000111
sele order from deta
---- ------------- ---- ----
2 0 0 SEARCH TABLE objects USING INTEGER PRIMARY KEY (rowid=?)
3 0 1 SCAN TABLE ancestors AS a
3 1 0 SEARCH TABLE objects AS f USING INTEGER PRIMARY KEY (rowid=?)
1 0 0 COMPOUND SUBQUERIES 0 AND 0 (UNION ALL)
0 0 0 SCAN SUBQUERY 1
第二个结果大约快15倍,因为我们在对象上使用PK索引来获取初始行,而视图似乎扫描了整个表,仅在找到所有行的祖先后才在叶节点上进行过滤
有什么方法可以编写视图,以便可以对将用于优化初始查询的消费选择施加约束?
答案 0 :(得分:0)
您要在第一个子查询中移动WHERE leafid = 157609
。这是push-down optimization,SQLite会尽可能尝试这样做。
但是,只有在数据库能够证明结果相同的情况下才有可能。对于这个特定的查询,您知道该转换是有效的,但是目前,尚无算法可以为递归CTE提供这种证明。