LEFT JOIN在Postgres中的分区表上不能很好地发挥作用吗?

时间:2019-08-09 23:17:23

标签: postgresql partitioning

我在Postgres中有一个查询,该查询连接了2个表,其中一个已分区。执行计划表明,即使我在查询中包括分区键,查询也会击中表的所有分区。

我终于意识到问题是我遇到的LEFT JOIN。如果我将A LEFT JOIN B替换为A, B,则Postgres将仅针对1个分区而不是所有分区。

有人知道这是否是Postgres执行计划程序中的错误吗?

这里是简化的查询:

EXPLAIN SELECT in_memory_table.my_col
    FROM (SELECT '2019-08-09 19:00:00+00:00') in_memory_table(my_col)
    LEFT JOIN partitioned_table
    ON (partitioned_table.id = '1111111111111111122222222222222'
        AND partitioned_table.my_col = in_memory_table.my_col);

这产生了这个执行计划:

                                                             QUERY PLAN                                                             
------------------------------------------------------------------------------------------------------------------------------------
 Nested Loop Left Join  (cost=0.56..58.28 rows=1 width=8)
   Join Filter: (partitioned_table_201908_partition.my_col = ('2019-08-09 19:00:00+00'::timestamp with time zone))
   ->  Result  (cost=0.00..0.01 rows=1 width=8)
   ->  Append  (cost=0.56..58.17 rows=7 width=8)
         ->  Index Scan using partitioned_table_201908_partition_pkey on partitioned_table_201908_partition  (cost=0.56..8.58 rows=1 width=8)
               Index Cond: (id = '1111111111111111122222222222222'::uuid)
         ->  Index Scan using partitioned_table_201909_partition_pkey on partitioned_table_201909_partition  (cost=0.15..8.17 rows=1 width=8)
               Index Cond: (id = '1111111111111111122222222222222'::uuid)
         ->  Index Scan using partitioned_table_201910_partition_pkey on partitioned_table_201910_partition  (cost=0.15..8.17 rows=1 width=8)
               Index Cond: (id = '1111111111111111122222222222222'::uuid)
         ->  Index Scan using partitioned_table_201911_partition_pkey on partitioned_table_201911_partition  (cost=0.15..8.17 rows=1 width=8)
               Index Cond: (id = '1111111111111111122222222222222'::uuid)
         ->  Index Scan using partitioned_table_201912_partition_pkey on partitioned_table_201912_partition  (cost=0.15..8.17 rows=1 width=8)
               Index Cond: (id = '1111111111111111122222222222222'::uuid)
         ->  Index Scan using partitioned_table_202001_partition_pkey on partitioned_table_202001_partition  (cost=0.15..8.17 rows=1 width=8)
               Index Cond: (id = '1111111111111111122222222222222'::uuid)
         ->  Index Scan using partitioned_table_pkey on partitioned_table_000000_partition  (cost=0.70..8.72 rows=1 width=8)
               Index Cond: (id = '1111111111111111122222222222222'::uuid)
(18 rows)

如果我改为这样做:

EXPLAIN SELECT in_memory_table.my_col
    FROM (SELECT '2019-08-09 19:00:00+00:00') in_memory_table(my_col),
    partitioned_table
    WHERE (partitioned_table.id = '1111111111111111122222222222222'
        AND partitioned_table.my_col = in_memory_table.my_col);

然后执行计划看起来像我期望的样子:

                                                          QUERY PLAN                                                          
------------------------------------------------------------------------------------------------------------------------------
 Append  (cost=0.56..8.59 rows=1 width=8)
   ->  Index Scan using partitioned_table_201908_partition_pkey on partitioned_table_201908_partition  (cost=0.56..8.58 rows=1 width=8)
         Index Cond: (id = '1111111111111111122222222222222'::uuid)
         Filter: (result_timestamp = '2019-08-09 19:00:00+00'::timestamp with time zone)

为什么LEFT JOIN版本会影响所有分区?

其他信息

  • 我正在使用Postgres 11.1
  • my_col是分区键(按范围分区)
  • 我为什么使用LEFT JOIN?这是一个简化的版本,真正的版本使用的是LEFT OUTER JOIN,但是很难问到(我无法在其中将ON转换为WHERE)。

0 个答案:

没有答案