首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >连接优化PostgresSQL

连接优化PostgresSQL
EN

Stack Overflow用户
提问于 2021-09-06 16:38:03
回答 2查看 54关注 0票数 0

我有2个表:呼叫(10,000行),客户关系管理(2,500万行)我想做呼叫左加入CRM。

代码语言:javascript
复制
select * 
from calls a
left join crm b
on (
(a.customerID = b.customerID)
OR
(a.Number1 in (b.Number_A,b.Number_B))
OR
(a.Number2 in (b.Number_A,b.Number_B))
);

当我只执行customerID连接时,它运行得很好。但上面的代码会导致超时并导致崩溃。

EN

回答 2

Stack Overflow用户

发布于 2021-09-06 17:19:34

我建议使用多个left join

代码语言:javascript
复制
select c.*, 
       coalesce(cc.col1, c1a.col1, c1b.col1, c2a.col1, c2b.col1)
from calls c left join
     crm cc
     on c.customerID = cc.customerID left join
     crm c1a
     on c.Number1 = c1a.Number_A left join
     crm c1b
     on c.Number1 = c1b.Number_B left join
     crm c2a
     on c.Number2 = c2a.Number_A left join
     crm c2b
     on c.Number2 = c2b.Number_B;

这样就可以利用crm(CustomerId)crm(Number1)crm(Number2)上的索引。

票数 0
EN

Stack Overflow用户

发布于 2021-09-06 20:05:41

有时,当用两个用UNION粘合在一起的查询替换一个包含两个条件的OR查询时,这会产生一个更好的执行计划。我从来不明白为什么DBMS优化器自己不考虑这一点。我不知道这对PostgreSQL是不是真的。但这可能值得一试。

在您的例子中,查询中有一个外连接。这让事情变得复杂起来。使用单独的查询,我们可以同时获得呼叫的外部联接和匹配crm行,在这种情况下必须消除前者。

代码语言:javascript
复制
select *
from
(
  select * from calls left join crm on crm.customerID = calls.customerID
  union
  select * from calls left join crm on crm.number_a = calls.number1
  union
  select * from calls left join crm on crm.number_a = calls.number2
  union
  select * from calls left join crm on crm.number_b = calls.number1
  union
  select * from calls left join crm on crm.number_b = calls.number2
) data
order by rank() over (partition by calls.id order by case when crm.id is null then 2 else 1 end)
fetch first row with ties;

为了更快地工作,查询中的每列应该有一个索引,即6个单列索引。

这是否比原始查询更快取决于很多因素。主要:匹配越少越好。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69077843

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档