PostgreSQL 两个连接和它们之间的 NOT EQUAL 子句的性能
Posted
技术标签:
【中文标题】PostgreSQL 两个连接和它们之间的 NOT EQUAL 子句的性能【英文标题】:Performance of PostgreSQL two joins and NOT EQUAL clause between them 【发布时间】:2020-03-28 19:34:53 【问题描述】:基本上我们有一个事实表(实际上它是分区的并且具有相当宽的结构) - 事务表,一旦事务被加载并且永远不会更改它拥有的 ID,并且我们有两个字段是相同的 ID维度(此维度的属性会不时更改)。 我们需要从维度表的一行中查询事实表中所有“名称”不同的记录。 我们如何才能在那里获得最佳性能?
另外:
事实表和维度表都是按计划填充的,因此如果我们可以通过添加一些映射表来提高性能 - 可以这样做 索引、数组、复合索引 - 随便 PostgreSQL 10(如果 11 和 12 中的内容可以提供帮助 - 不胜感激) 代码如下任何关于如何重组它以更快地获得相同结果的想法 - 将不胜感激。
事实表
select
generate_series as row_id
,(random()*1000000)::bigint as id1
,(random()*1000000)::bigint as id2
into table_fact
from generate_series(1,10000000);
维度表
select
generate_series as row_id
,'Dimension #' || (random()*10000)::bigint as dim
into table_dim
from generate_series(1,1000000);
查询
select
tf.row_id
,tf.id1
,tf.id2
,td1.dim
,td2.dim
from table_fact tf
left join table_dim td1 on tf.id1=td1.row_id
left join table_dim td2 on tf.id2=td2.row_id
where not (td1.dim = td2.dim);
【问题讨论】:
使用你的设置脚本,table_fact 中的几乎每一行都会被返回。 (在我执行它时,只有 12 个被省略)。一般情况会这样吗? 这些 table_factid1,id2 字段是否应该引用维度表?在这种情况下,它们应该是外键。此外,为了有意义,table_dim.dim 可能需要是唯一的(并且不是 NULL) 【参考方案1】:您的查询应该没问题,因为您应该在适当的维度列上有索引。但是left join
似乎不合适,因为您需要匹配。所以:
select tf.row_id , tf.id1, tf.id2, td1.dim ,td2.dim
from table_fact tf join
table_dim td1
on tf.id1 = td1.row_id join
table_dim td2
on tf.id2 = td2.row_id
where td1.dim <> td2.dim;
因为你需要两个维度的名字,我觉得你需要扫描table_fact
。
【讨论】:
嗯,是的,查询本身没问题,但它的性能并不如我所愿。您提出的查询具有完全相同的执行计划,并且在我的环境中,提议的数据集具有相同的 35 秒。我的主要问题是另一个问题:如何改进这一切,整个设置,以提高性能。 @DenysSmakovskyi 。 . .很难在不同列之间进行优化比较。您可以在事实表中放置一个标志,指示这两个名称是否相同,并将该标志包含在索引中。您可能不希望仅在布尔列上建立索引,因为它的选择性不是很高。 列会有所帮助,但维度表可能会不时更改。在这种情况下,我不能将这样的列放在事实表中,因为事实表不应该有任何更新。以上是关于PostgreSQL 两个连接和它们之间的 NOT EQUAL 子句的性能的主要内容,如果未能解决你的问题,请参考以下文章