在某些情况下,JOIN 子句中的 USING 构造会引入优化障碍吗?

Erw*_*ter 38 postgresql performance join optimization select

我注意到查询子句中USING构造(而不是ON)可能会在某些情况下引入优化障碍。FROMSELECT

我的意思是这个关键词:

选择 *
从一个
加入 b使用(a_id)

只是在更复杂的情况下。

上下文:this comment to this question

我用这个了很多,从来没有发现过这么远。我会对展示效果的测试用例或任何指向更多信息的链接非常感兴趣。我的搜索努力是空的。

完美的答案将是一个测试用例,USING (a_id)与替代 join 子句相比,它的性能较差ON a.a_id = b.a_id——如果这真的可以发生的话。

Chr*_*ers 12

Erwin:我同意 USING 导致严格排序的想法,这很可能会产生许多边缘情况,在这些情况下,最佳计划将被排除在外。我最近帮助了一个在他的查询中有类似问题的人:

LEFT JOIN ( 
     a 
     JOIN b ON a.id = b.a_id
     JOIN c ON b.c_id = c.id
) ON a.id = something.a_id
LEFT JOIN (
     table1 t1
     JOIN table2 t2 ON t1.some_field = t2.other_field
     JOIN talbe3 t3 ON t2.yafield = t3.something_else
) ON ....
repeat a few more times
Run Code Online (Sandbox Code Playgroud)

在他的情况下,这些连接块中最糟糕的是导致嵌套循环连接通过大约 200k 行,大约 20k 次(做数学计算),并且由于无法将键推送到索引,因此它是顺序扫描。这意味着由于级联计划更改,整个查询需要大约 3 小时才能运行。通过分配左连接,键可以被按下,查询会在几秒钟内运行。当然,这并不完全等价,这就是为什么规划器不能将它们视为等价的,因此只能将该计划作为散列连接,然后在其中执行嵌套循环,这非常缓慢。

任何时候你严格地强制按照一定的顺序进行连接,你就会引入在计划执行中关键过滤器信息可能不可用的情况,因此稍后在快速索引扫描/散列连接中可能会做些什么在嵌套循环/顺序扫描中可能必须慢得多,因此虽然上述片段不是立即等效的,但它显示了相同的问题。