您的查询,已重写且100%等价:
SELECT count(*)
FROM product_categories pc
JOIN customers c USING (organization_id)
JOIN total_sales ts ON ts.customer_id = c.id
JOIN performance_analyses pa ON pa.total_sales_id = ts.id
WHERE pc.organization_id = 3
AND c.active -- boolean can be used directly
AND c.visible
AND ts.product_category_id = pc.id
AND ts.period_id = 193
AND pa.size > 0;
另一个答案建议将所有条件移到FROM
列表中的连接子句和顺序表中。这可能适用于具有相对原始查询计划程序的某些其他RDBMS。但是,尽管它对Postgres也没有害处,但它对查询的性能 也 没有影响 -假设使用默认服务器配置。手册:
明确的内连接语法(INNER JOIN
,CROSS JOIN
,或古拙JOIN
)在语义上的相同列出输入关系FROM
,所以 。
大胆强调我的。还有更多内容,请阅读手册。
关键设置为join_collapse_limit
(默认为 8 )。无论您如何安排表格以及是否将条件写为WHERE
或JOIN
子句,Postgres查询计划器都会以它希望最快的方式重新安排您的4个表格。没什么区别。(对于某些其他类型的无法自由重排的联接,情况并非如此。)
重要的是,这些不同的连接可能性在语义上等效,但是执行成本可能大不相同。因此,计划者将探索所有这些因素,以找到最有效的查询计划。
最后,WHERE id IN (<subquery>)
通常 不 等同于联接。对于右侧的重复匹配值,它不会在左侧乘以行。子查询的列在其余查询中不可见。联接可以将具有重复值的行相乘,并且可见列。 在这两种情况下,您的简单子查询都将挖掘一个唯一的列,因此在这种情况下没有有效的区别-除了IN (<subquery>)
通常(至少有点)更慢且更冗长。使用联接。