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_us
、id_invmat
、id_struttura
和id_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
上的每个辅助表上创建索引来加快速度。
我对这个查询有疑问。它进入循环,我的意思是 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_us
、id_invmat
、id_struttura
和id_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
上的每个辅助表上创建索引来加快速度。