【问题标题】:Why does PostgreSQL sorts on a boolean WHERE condition?为什么 PostgreSQL 对布尔 WHERE 条件进行排序?
【发布时间】:2019-10-24 22:50:27
【问题描述】:

我正在对一堆物化视图测试一些查询。它们都具有相同的结构,例如:

EXPLAIN ANALYZE SELECT mr.foo, ..., CAST(SUM(mr.bar) AS INTEGER) AS stuff
    FROM foo.bar mr
    WHERE
        mr.a = 'TRUE' AND
        mr.b = 'something' AND
        mr.c = '12'
    GROUP BY
        mr.a,
        mr.b,
        mr.c;

很明显,系统给了我一个不同的查询计划,但如果(且仅当)WHERE 子句涉及布尔列(如示例中),则计划程序总是在完成之前对结果集进行排序。示例:

Finalize GroupAggregate  (cost=16305.92..16317.98 rows=85 width=21) (actual time=108.301..108.301 rows=1 loops=1)
   Group Key: festivo, nome_strada, ora
   ->  Gather Merge  (cost=16305.92..16315.05 rows=70 width=77) (actual time=108.279..109.015 rows=2 loops=1)
         Workers Planned: 2
         Workers Launched: 2
         ->  Partial GroupAggregate  (cost=15305.90..15306.95 rows=35 width=77) (actual time=101.422..101.422 rows=1 loops=3)
               Group Key: festivo, nome_strada, ora
               ->  Sort  (cost=15305.90..15305.99 rows=35 width=21) (actual time=101.390..101.395 rows=28 loops=3)
                     Sort Key: festivo
                     Sort Method: quicksort  Memory: 25kB
                     ->  Parallel Seq Scan on sft_vmv3_g3 mr  (cost=0.00..15305.00 rows=35 width=21) (actual time=75.307..101.329 rows=28 loops=3)
                           Filter: (festivo AND ((nome_strada)::text = '16th St'::text) AND (ora = '12'::smallint))
                           Rows Removed by Filter: 277892

我对这种方法非常好奇,但我仍然没有找到解释。

【问题讨论】:

  • 它可能认为排序比 HashAggregate 便宜。 work_mem 的设置是什么? (顺便说一句:您应该将布尔列用作布尔值,例如 where mr.a 或提供适当的布尔文字而不是字符串,例如 where mr.a = true
  • work_mem 是 4MB。关于文字,根据Postgres docs 应该没关系。
  • 您可以尝试增加 work_mem(例如增加到 64MB),看看这是否会将计划更改为 HashAggregate
  • 如果a 是一个布尔值,为什么要将它与字符串常量进行比较?

标签: sql postgresql sql-execution-plan explain query-planner


【解决方案1】:

我很好奇你为什么不将逻辑表述为:

SELECT true as a, 'something' as b, '12' as c, CAST(SUM(mr.bar) as INTEGER)
FROM foo.bar as mr
WHERE mr.a AND
      mr.b = 'something' AND
      mr.c = '12';

这是一个聚合查询(因为SELECT 中的SUM())并且没有明确的GROUP BY。我认为它应该产生一个更优化的执行计划。此外,即使没有符合条件的行,它也将始终返回一行。

【讨论】:

  • WHERE 条件是否应该以WHERE mr.a = 'TRUE' AND... 开头? mr.a 似乎是 VARCHAR 或类似性质的东西,而不是 BOOLEAN。
  • @a_horse_with_no_name 。 . .这是一个没有GROUP BY 的聚合查询。所有此类查询都只返回一行。
  • @BobJarvis 。 . .问题的文本在WHERE 中提到了一个布尔列。唯一合理的候选人是a
  • @a_horse_with_no_name 。 . . dbfiddle.uk/….
猜你喜欢
  • 1970-01-01
  • 2019-03-12
  • 1970-01-01
  • 2010-10-28
  • 2015-03-16
  • 1970-01-01
  • 1970-01-01
  • 2017-12-23
  • 1970-01-01
相关资源
最近更新 更多