【问题标题】:PostgreSQL ON vs WHERE when joining tables?加入表时PostgreSQL ON vs WHERE?
【发布时间】:2018-11-01 19:20:45
【问题描述】:

我有 2 个表 customercoupons,客户可能分配有也可能没有分配 reward_id,因此它是一个可为空的列。一个客户可以有很多优惠券,优惠券属于一个客户。

+-------------+------------+
|   coupons   | customers  |
+-------------+------------+
| id          | id         |
| customer_id | first_name |
| code        | reward_id  |
+-------------+------------+
customer_id column is indexed

我想在 2 个表之间进行连接。

我的尝试是:

select c.*, cust.id as cust_id, cust.first_name as cust_name
from coupons c
join customer cust
on c.customer_id = cust.id and cust.reward_id is not null

但是,我认为reward_id 上没有索引,所以我应该在where 子句中移动cust.reward_id is not null

select c.*, cust.id as cust_id, cust.first_name as cust_name
from coupons c
join customer cust
on c.customer_id = cust.id
where cust.reward_id is not null

我想知道第二次尝试是否会比第一次更有效率。

【问题讨论】:

  • 创建缺失的索引而不是移动条件。优化器无论如何都会移动它们,如果它看到了它的好处。
  • @stickybit 假设 reward_id 已编入索引,第二个查询会是更好的选择吗?
  • @tkhuynh 。 . .他们应该有相同的执行计划。
  • 两者都会产生完全相同的执行计划
  • @tkhuynh 。 . .这可能是由于缓存效应。或者如果差异非常小(比如

标签: sql postgresql performance inner-join


【解决方案1】:

在 PostgreSQL 内连接中,过滤条件放在 ON 子句还是 WHERE 子句中都不会影响查询结果或性能。

以下是更详细地探讨该主题的指南:https://app.pluralsight.com/guides/using-on-versus-where-clauses-to-combine-and-filter-data-in-postgresql-joins

【讨论】:

【解决方案2】:

如果你自己看执行计划会更好。在您的 select 语句之前添加 EXPLAIN ANALYZE 并执行两者以查看差异。

方法如下:

EXPLAIN ANALYZE select ...

它有什么作用?它实际上执行 select 语句并返回查询优化器选择的执行计划。如果没有ANALYZE关键字,它只会估计执行计划,而不会在后台实际执行语句。

数据库不会同时使用两个索引,因此在customer(id) 上有一个索引将使其无法在customer(reward_id) 上使用索引。此条件实际上将被视为正确行为的过滤条件。

您可以试验这样创建的部分索引的性能:customer(id) where reward_id is not null。这将减少索引大小,因为它只会存储分配了reward_id 的这些客户 ID。

我通常喜欢将关系/连接逻辑从应用的条件中分离出来,我自己将它们放在WHERE 子句中,因为它在那里更明显,并且如果有更多的变化,将来更容易阅读。

我建议您自己看看可能的性能提升,因为这取决于有多少数据以及reward_id 可能的低基数。例如,如果大多数行的该列都填充了一个值,则它不会产生太大的差异,因为索引大小(正常与部分)几乎相同。

【讨论】:

  • 我确实使用EXPLAIN ANALYZE 来查看 2 个查询的性能,我注意到对于大量记录,第二个查询的性能更好。但是我仍然想确认将cust.reward_id is not null 移动到WHERE 子句是否是一个更好的选择。
猜你喜欢
  • 2016-11-07
  • 2011-02-07
  • 2014-03-29
  • 2010-11-04
  • 1970-01-01
  • 1970-01-01
  • 2017-11-18
  • 1970-01-01
  • 2021-11-14
相关资源
最近更新 更多