最近我对Clojure越来越熟悉了,我对懒惰序列评估的想法很感兴趣,它只在必要时计算值。
我使用PostgreSQL DB工作很多,并且在使用LIMIT子句时遇到了不同的查询性能。例如查询
SELECT * FROM(
SELECT id FROM foo1
INTERSECT
SELECT id FROM foo2) AS subquery
LIMIT 50
将具有与
相同的执行时间SELECT id FROM foo1
INTERSECT
SELECT id FROM foo2.
这表明Postgres首先评估整个结果,然后获得前50行。这种行为与懒惰的想法相反,因为DB处理数据不需要得到最终答案。但另一方面查询
SELECT * FROM foo1 INNER JOIN foo2 ON foo1.id=foo2.id LIMIT 50
比
表现得更好SELECT * FROM foo1 INNER JOIN foo2 ON foo1.id=foo2.id.
有人知道哪些Postgres操作支持LIMIT懒惰吗?
答案 0 :(得分:1)
对于初学者,您的查询不等同,除非id
在两个表中都是唯一的。 INTERSECT
处理重复项的方式与INNER
或OUTER JOIN
不同。缺少关键字 ALL
会使差异更大。 Per documentation:
另一方面,
INTERSECT
的结果不包含任何重复的行,除非 指定了ALL
选项。使用ALL
时,行中有m
个重复的行 左表格和右侧表格中的n
重复项将显示为min(m,n)
结果集中的时间。
联接生成一个笛卡尔积,即m*n
行,用于匹配重复项。因此查询计划不能使用相同的代码路径。
要获得相差较少的结果(但仍然不等同除了唯一的id
),请改用:
SELECT id FROM foo1
INTERSECT ALL -- don't fold dupes
SELECT id FROM foo2
LIMIT 50;
SELECT * FROM foo1 JOIN foo2 USING (id) LIMIT 50; -- return single id column
这是a fiddle to play with(第9.3.1页)。 sqlfiddle.com上的版本现在已经过时了。而是自己测试最新版本。
很多更多的时间和智能进入连接的优化,这些连接更常用于几个数量级。我几乎没有使用INTERSECT
,因为它经常产生较差的查询计划。在对第9页的快速测试中,我只能从INTERSECT
中获得连续扫描,其中连接使用更快的索引扫描。我不知道第9.4页中有关INTERSECT
的任何新闻。
有可能改进,特别是在涉及独特索引的情况下。我想没有人关心它,因为INTERSECT
不如其他操作那么受欢迎。
我知道UNION ALL
与LIMIT
结合使用的非常好的用例,可以从“懒惰评估”中受益,但是: