【问题标题】:Boolean column in index and filter sections of explain in postgrespostgres中解释的索引和过滤部分中的布尔列
【发布时间】:2015-11-09 13:15:51
【问题描述】:

我有一个带有布尔列的表 - "is_woman" bool DEFAULT true

我有一个包含此列的 btree 索引(以及其他一些,例如年龄、城镇等)-is_woman ASC NULLS LAST

我对此专栏有疑问 - is_woman IS FALSE

结果我得到了解释:

-> Index Scan using woman_idx on superjob (cost=... rows=... width=32) (actual time=... rows=... loops=1)
 Index Cond: (town = 1) AND (is_woman = false) AND (age >= 35) AND (age <= 60))
 Filter: (is_woman IS FALSE)

为什么有两个 is_woman 条件?一个在索引部分,第二个在过滤器中?

更新

在@dmitry 的帮助下,我创建了两个partial indexes:一个为is_woman is false 的男性,第二个为is_woman is true 的女性。

Explain 同一个查询:

Bitmap Index Scan on is_woman_woman_idx (...) (actual time=469.446..469.446 rows=406867 loops=1) Index Cond: ((age >= 1) AND (town = 1)) Execution time: 1827.239 ms

没有Filter 部分,此查询运行得更快:

  • 实际时间2.227..2754.378469.446..469.446
  • 执行时间2792.804 ms1827.239 ms

【问题讨论】:

    标签: postgresql boolean sql-execution-plan b-tree-index


    【解决方案1】:

    更新

    我看不出这个EXPLAIN 有什么问题,除了您正在索引boolean 列(显然,列具有低基数字段)。 可能使用 Partial Index 的定义如下:

    CREATE INDEX ON yourtable WHERE is_woman = FALSE;
    

    至于问题本身,您有一个带有WHERE ... 条件的查询。 Postgres planner/optimizer 决定使用 woman_idx 索引扫描而不是顺序扫描 - Index Cond 指示用于索引扫描。

    如果你能看到Filter 语句,这意味着计划节点检查它扫描的每一行的条件(在我们的例子中是每个woman_idx 扫描),并且只输出那些通过条件。有关详细信息,请查看EXPLAIN 文档。

    【讨论】:

    • 好的。也许 boolean 的基数很低,但 postgres 规划器决定使用它,因为 Index Cond 部分中的此列。但是为什么过滤器部分有相同的列?
    • 更新了最后一段以进行澄清-Filter 语句仅表明在实际扫描索引的顶部-在特定条件下花费了额外的开销@Anton
    • 谢谢,我了解Filter 部分的“原因”,但此类检查将始终返回true
    • 作为测试,我创建了is_woman_int int2 列,在此列中创建了附加索引,并进行了两个查询Index Scan using woman_idx on superjob (...) (actual time=2.227..2754.378 rows=406867 loops=1) Index Cond: ((age &gt;= 1) AND (is_woman = true) AND (town = 1)) Filter: (is_woman IS TRUE) Planning time: 5.566 ms Execution time: 2792.804 msIndex Scan using woman_int_idx on superjob (...) (actual time=0.900..2829.579 rows=406867 loops=1) Index Cond: ((age &gt;= 1) AND (is_woman_int = 1) AND (town = 1)) Planning time: 0.406 ms Execution time: 2866.855 ms
    • 对,只要您从结果中获得相当数量的记录,过滤器就会出现,换句话说,您的 WHERE ... 子句不够窄,对于 Boolean 列,它几乎总是一个案例(低基数字段) 基本扫描从idx 结果开始。当插入约 40 万条记录时,您将在整数索引 woman_int_idx 上看到 Filter,例如 is_woman_int = 100EXPLAIN 也会显示filter 日志,因为is_woman_int = 100 将返回大量(相对于表记录#)具有相同基数@Anton 的记录
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-02
    • 2015-08-30
    • 2016-02-19
    • 1970-01-01
    • 2017-04-25
    • 2011-05-07
    相关资源
    最近更新 更多