我怎样才能理解sqlite查询计划?

时间:2015-01-14 01:38:09

标签: sqlite sql-execution-plan

我在SQLite上执行了一个查询,计划部分是

0|1|5|SCAN TABLE edges AS e1 (~250000 rows)
0|0|0|EXECUTE CORRELATED SCALAR SUBQUERY 2
2|0|0|SEARCH TABLE dihedral USING AUTOMATIC
COVERING INDEX (TYPE=? AND EDGE=?) (~7 rows)
0|0|0|EXECUTE CORRELATED SCALAR SUBQUERY 3
3|0|0|SEARCH TABLE bounds USING AUTOMATIC
COVERING INDEX (FACE=? AND EDGE=?) (~7 rows)

WHERE中的查询是

exists (select dihedral.edge from dihedral where ihedral.type=2 and dihedral.edge=e1.edge) and
exists (select bounds.edge from bounds where bounds.face=f1.face and bounds.edge=e1.edge) and

我理解这不是一个高效的查询,我只想提高性能。

这是我的猜测:

  1. 没有子查询扁平化,对吧?

  2. 两个存在的子查询引入了相关的子查询,因为它们实际上是作为索引的嵌套循环执行的,对吗?

  3. 读取查询,因为表二面角和边界是独立的,两者都与外边缘表相关,因此没有索引的计算复杂度为O(n^2)。但是,由于有覆盖指数,性能应该好多了吧?我发现在wiki上,索引的性能更好O(log(N)),所以整体性能应该是O(n*log(N)),这是对的吗?

  4. 有谁能帮我理解发生了什么?谢谢。

1 个答案:

答案 0 :(得分:0)

SQLite确实支持subquery flattening,但这对于像这里这样的EXISTS子查询是不可能的。

AUTOMATIC显示数据库仅为此查询创建临时索引。 这强烈表明您应该永久创建这些索引:

CREATE INDEX dihedral_type_edge ON dihedral(type, edge);
CREATE INDEX bounds_face_edge ON bounds(face, edge);

外部查询遍历所有edge行,并且对于每一行,在索引中搜索。 这将导致O(edge * (log(dihedral) + log(bounds)))。 临时索引创建需要对这些表进行排序,因此整个运行时最终为O(dihedral*log(dihedral) + bounds*log(bounds) + edge*(log(dihedral)+log(bounds)))