我发现,运行ANALYZE
导致特定JOIN
我在两个牌桌之间制作的效果非常差。
假设以下架构:
CREATE TABLE a ( id INTEGER PRIMARY KEY, name TEXT );
CREATE TABLE b ( a NOT NULL REFERENCES a, value INTEGER, PRIMARY KEY(a, b) );
CREATE VIEW ab AS SELECT a.name, b.text, MAX(b.value)
FROM a
JOIN b ON b.a = a.id;
GROUP BY a.id
ORDER BY a.name
表a约为10K行,表b约为48K行(表a中每行约5行)。
ANALYZE
之前
现在,当我运行以下查询时:
SELECT * FROM ab;
查询计划如下所示:
1|0|0|SCAN TABLE b
1|1|1|SEARCH TABLE a USING INTEGER PRIMARY KEY (rowid=?)
这是一个很好的计划,b更大,我希望它在外循环中,利用表a中的索引。它在一秒钟内完成。
ANALYZE
当我再次执行相同的查询时,查询计划会产生两个表扫描:
1|0|1|SCAN TABLE a
1|1|0|SCAN TABLE b
这是最佳选择。由于某种原因,查询规划器认为10K行的外循环和48K行的内循环更适合。这需要大约1.5分钟才能完成。
我应该调整表b中的索引,使其在ANALYZE
之后有效吗?还有什么要改变索引/架构吗?
我只是试着在这里理解这个问题。我使用CROSS JOIN
来解决这个问题,但这感觉很脏,而且我真的不明白为什么规划人员会采用比未分析计划慢几个数量级的计划。它似乎与GROUP BY
有关,因为查询规划器将表b放在没有它的外部循环中(但这会使查询对我想要的东西无效)。
答案 0 :(得分:0)
通过调整视图定义中的GROUP BY
子句意外地找到了答案。我没有加入a.id
,而是在b.a
上进行分组,尽管它们具有相同的值。
CREATE VIEW ab AS SELECT a.name, b.text, MAX(b.value)
FROM a
JOIN b ON b.a = a.id;
GROUP BY b.a -- <== changed this from a.id to b.a
ORDER BY a.name
我仍然不完全确定它的区别是什么,因为它将相同的数据分组。