在 Postgres 中添加 INNER JOIN 子句会导致 SQL 性能下降

在 Postgres 中添加 INNER JOIN 子句会导致 SQL 性能下降

我有以下疑问

SELECT pri.*
  FROM patientreceiptitem pri 
  JOIN patientfinancialtransaction_patientreceiptitem pp ON pri.id = pp.receiptitems_id
  JOIN patientfinancialtransaction pft ON pp.patientfinancialtransaction_id = pft.id 
 WHERE pri.createtime >= '2020-03-01'
   AND pri.createtime < '2020-04-01'

它运行时间为 1.79 秒,输出 111,793 行

但是,当我添加一个更严格的条件时,如下所示:

 JOIN patientbillconcession pbc ON pbc.id = pft.concession_id

性能会急剧下降。输出 10,338 行数据现在需要 8.185 秒。如果我向表的 JOIN 子句添加条件,也会出现同样的性能下降pft

SELECT pri.*
  FROM patientreceiptitem pri 
  JOIN patientfinancialtransaction_patientreceiptitem pp ON pri.id = pp.receiptitems_id
  JOIN patientfinancialtransaction pft ON pp.patientfinancialtransaction_id = pft.id 
       AND pft.concession_id IS NOT NULL
 WHERE pri.createtime >= '2020-03-01'
   AND pri.createtime < '2020-04-01'

concession_id已在pft表中编入索引。

任何指点都将十分有帮助。

我在 Arch Linux 上运行 Postgres 12。我的客户端是 DBeaver 7.3.2。

更新 1:我发现将以下内容更改为 LEFT JOIN 可在 1.914 秒内完成查询: LEFT JOIN patientbillconcession pbc ON pbc.id = pft.concession_id

但添加AND pft.concession_id IS NOT NULLWHERE 子句后,性能再次降低至 7.938 秒

答案1

由于值无法连接,pft.concession_id IS NOT NULL因此查询中的having无关紧要。它们将被自然排除,因为要求存在匹配的记录。NULLJOIN patientbillconcessionpatientfinancialtransation

最简单的方法是从...开始EXPLAIN然后 PostgreSQL 可以告诉您为什么返回结果需要这么长时间:

EXPLAIN SELECT pri.* FROM patientreceiptitem pri ...

相关内容