查询1:
select *
from a
LEFT JOIN p ON a.product_id = p.web_id
LEFT JOIN m ON p.manufacturer_id = m.web_id
LEFT JOIN a add ON a.address_id = add.web_id
LEFT JOIN c ON c.web_id = a.owner_id
LEFT JOIN a ca ON c.main_address_id = ca.web_id
LEFT JOIN d ON a.web_id = d.equipment_id
LEFT JOIN s ON d.last_segment_id = s.web_id
LEFT JOIN oh ON s.order_header_id = oh.web_id
LEFT JOIN f ON s.folder_id = f.web_id
LEFT JOIN ve on a.web_id = ve.equipment_id
where ve.date_updated >= now() - interval '10000 min'
查询二:
select *
from a
LEFT JOIN p ON a.product_id = p.web_id
LEFT JOIN m ON p.manufacturer_id = m.web_id
LEFT JOIN ve on a.web_id = ve.equipment_id
LEFT JOIN a add ON a.address_id = add.web_id
LEFT JOIN c ON c.web_id = a.owner_id
LEFT JOIN a ca ON c.main_address_id = ca.web_id
LEFT JOIN d ON a.web_id = d.equipment_id
LEFT JOIN s ON d.last_segment_id = s.web_id
LEFT JOIN oh ON s.order_header_id = oh.web_id
LEFT JOIN f ON s.folder_id = f.web_id
where ve.date_updated >= now() - interval '10000 min'
这两个查询之间的唯一区别是左join with ve表的位置。
我相信这两个查询的输出总是相同的,对吗?
查询1能够在5秒内执行,而查询2持续约4分钟。表a中的记录总数约为2000万条。为什么查询1更快?
1条答案
按热度按时间8mmmxcuj1#
连接条件的顺序并不重要,查询在语义上是相同的。执行时间差必须连接到
join_collapse_limit
:每当生成不超过这个数量的项目列表时,计划器将将显式
JOIN
结构(FULL JOIN
s除外)重写为FROM
项目列表。较小的值会减少计划时间,但可能会产生较差的查询计划。默认情况下,此变量的设置与
from_collapse_limit
相同,这适用于大多数用途。将其设置为1可防止对显式JOIN
s进行任何重新排序。因此,查询中指定的显式联接顺序将是联接关系的实际顺序。由于查询计划器并不总是选择最佳连接顺序,高级用户可以选择暂时将此变量设置为1,然后显式指定他们所需的连接顺序。更多信息请参见Section 14.3。请注意,查询连接八个以上的表。
如果您有很多这样的连接,并且不想重写它们,并且您不介意优化器花费更多的时间,那么可以增加
join_collapse_limit
和from_collapse_limit
。