Postgres 查询左连接花费太多时间

Postgres query left join take too time

我对这个查询有疑问。它进入循环,我的意思是 15 分钟后查询未完成 但是,如果删除其中一个左连接有效 我哪里错了?

Select distinct a.sito,
Count(distinct a.id_us) as us,
Count (distinct b.id_invmat) as materiali,
Count (distinct c.id_struttura) as Struttura,
Count(distinct d.id_tafonomia) as tafonomia
From us_table as a
Left join invetario_materiali as b on a.sito=b.sito
Left join struttura_table as c on a.sito=c.sito
Left join tafonomia_table as d on a.sito=d.sito
Group by a.sito
Order by us

谢谢 E

不幸的是 COUNT(DISTINCT ...) 使用索引很难改进。但是,我们至少可以尝试添加涵盖查询中所有连接的索引:

CREATE INDEX inv_mat_idx ON invetario_materiali (sito, id_invmat);
CREATE INDEX strut_tbl_idx ON struttura_table (sito, id_struttura);
CREATE INDEX taf_tbl_idx ON tafonomia_table (sito, id_tafonomia);

请注意,上述索引只会帮助连接,不会影响 sito 的聚合步骤和每组的非重复计数。正如@jarlh 在评论中指出的那样,SELECT DISTINCT 是多余的,因为您使用的是 GROUP BY,所以只需要简单的 SELECT.

假设id_usid_invmatid_strutturaid_tafonomia都是PRIMARY KEY CLUSTERED

您应该在连接列上添加索引:

CREATE INDEX IX_SITO ON us_table ( sito ASC) ;
CREATE INDEX IX_SITO ON invetario_materiali ( sito ASC) ;
CREATE INDEX IX_SITO ON struttura_table ( sito ASC) ;
CREATE INDEX IX_SITO ON tafonomia_table ( sito ASC) ;

你可以通过这种方式降低复杂性:

with
_us_table as (
    select sito, count(distinct a.id_us) us
    from us_table a
    group by sito
),
_invetario_materiali as (
    select sito, count(distinct b.id_invmat) materiali
    from invetario_materiali b
    group by sito
),
_struttura_table as (
    select sito, count(distinct c.id_struttura) Struttura
    from struttura_table c
    group by sito
),
_tafonomia_table as (
    select sito, count(distinct d.id_tafonomia) tafonomia
    from tafonomia_table d
    group by sito
)
Select a.sito, a.us, b.materiali, c.Struttura, d.tafonomia
From _us_table as a
Left join _invetario_materiali as b on a.sito=b.sito
Left join _struttura_table as c on a.sito=c.sito
Left join _tafonomia_table as d on a.sito=d.sito
Order by a.us;

应该会快很多

在这种情况下,相关子查询可能是最简单的方法:

select s.sito,
      (select count(*) from invetario_materiali m where s.sito = m.sito) as materiali,
      (select count(*) from struttura_tablest where s.sito = st.sito) as Struttura,
      (select count(*) from tafonomia_table t where s.sito = t.sito) as tafonomia
from (select sito, count(*) as us
      from us_table
      group by sito
     ) s
order by us;

这应该比您的版本快得多,原因有二。首先,它避免了外部聚合。其次,它避免了表格之间的笛卡尔积。

您可以通过在 sito 上的每个辅助表上创建索引来加快速度。