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 子句的性能的主要内容,如果未能解决你的问题,请参考以下文章

Python 操作Redis

python爬虫入门----- 阿里巴巴供应商爬虫

Python词典设置默认值小技巧

《python学习手册(第4版)》pdf

Django settings.py 的media路径设置

Python中的赋值,浅拷贝和深拷贝的区别