PostgreSQL 条件连接的性能 - 查询优化

Posted

技术标签:

【中文标题】PostgreSQL 条件连接的性能 - 查询优化【英文标题】:Performance over PostgreSQL conditional join - Query optimization 【发布时间】:2021-03-12 01:35:42 【问题描述】:

假设我有三个表,subscriptions,其中有一个名为 type 的字段,它只能有 2 个值;

    免费 高级版。

另外两个表称为premium_usersfree_users。我想从subscriptions 表开始执行左连接,但问题是,根据type 字段的值,我只会在一个或另一个表中找到匹配的行,即如果@987654327 @ 等于'FREE',那么匹配的行将只在free_users 表中,反之亦然。 我正在考虑一些方法来做到这一点,例如 LEFT JOINING 两个表,然后使用 COALESCE 函数获取非空值,或者使用 UNION,两个不同的查询在两个查询上都使用 INNER JOIN,但是我我不太确定在性能方面哪种方法是最好的。此外,正如您猜想的那样,free_users 表几乎是premium_users 表的五倍。您应该知道的另一件事是,我通过user_id 字段加入,这是free_userspremium_users 中的PK

所以,我的问题是:根据type 列的值将匹配到一个表或另一个表,这将是执行 JOIN 的最高效方式。如果不是两个表而是三个,甚至更多,这个解决方案会有什么不同吗?

免责声明:此数据库是 PostgreSQL,并且已经在生产环境中启动并运行,尽管我希望有一个 users 表,但短期内不会发生.

【问题讨论】:

您可以通过继承使用分区来创建统一用户表的外观,而无需停机或重组。 【参考方案1】:

在性能方面什么是最好的?好吧,你应该试试你的数据和系统。

我的建议是两个左连接:

select s.*,
       coalesce(fu.name, pu.name) as name
from subscriptions s left join
     free_users fu
     on fu.free_id = s.subscription_id and
        s.type = 'free' left join
     premium_users pu
     on pu.premium_id = s.suscription_id and
        s.type = 'premium';

您希望在 free_users(free_id)premium_users(premium_id) 上建立索引。这些可能是“免费的”,因为这些 id 应该是表中的主键。

如果您使用union all,那么优化器可能不会对连接使用索引。不使用索引可能会对性能产生可怕的影响。

【讨论】:

以上是关于PostgreSQL 条件连接的性能 - 查询优化的主要内容,如果未能解决你的问题,请参考以下文章

Postgresql 中不可预测的查询性能

Oracle查询性能优化

Oracle 查询性能优化(转)

postgresql性能优化-最大连接数

连接postgres特别消耗cpu资源而引发的PostgreSQL性能优化考虑

Postgresql 查询的过滤条件中的列上的字符串操作如何影响它选择的计划