【问题标题】:Why does Postgresql not use Index Only Scan on my composite index in this case?在这种情况下,为什么 Postgresql 不对我的复合索引使用仅索引扫描?
【发布时间】:2015-06-18 15:14:03
【问题描述】:

我的表有整数列“a”、“b”。 “a”只有少数(10**7)。为了加快速度,我创建了复合索引 (a,b)。我观察到了

select count(*) from tab where a=1; 

跑得也快

select count(*) from tab where a=2;

跑得很快,但是

select count(*) from tab where a=1 or a=2;

运行(哦,天哪)慢,同样是这样的

select count(*) from tab;

运行解释解释,快速查询使用

->  Index Only Scan using idx on tab

但是对于慢速查询,使用顺序扫描。

为什么会这样?为什么 Postgresql 后两个查询不使用相同的索引?只是查询计划器的不完善,还是不能使用 Index Only Scan 的更深层次的原因?

【问题讨论】:

  • 一个疯狂的猜测:你在 tab.a 上没有(有效的)统计信息,或者 tab.a 的大部分值是 1 或 2。
  • 尝试以这种方式更改第二个查询:select (select count(*) from tab where a=1)+(select count(*) from tab where a=2);,优化器应该对两个子查询使用 IndexOnlyScan。问题是优化器一般不喜欢or 条件。
  • @joop 重要吗,有多少个值 1 和 2? (大约有 1 和 2 的 1/10)。如果在 (a,b) 上构建了复合索引,那么无论有多少这样的记录,它都可以加快查询执行速度,所以我希望 Postgre 使用该索引。
  • @Renzo 正如预期的那样,您的查询运行得很快。您可能对复杂的“或”是正确的,但是,我希望至少最后一个 count( * ) 查询使用索引。请注意,迭代所有可能的“a”值并将部分计数()结果相加比直接计数()快得多。这让我感到惊讶,因为这基本上迫使 Postgre 遍历整个复合索引;为什么 Postgre 不自己做呢?我相信,这样的决定不需要“特殊知识”,但需要(大约)总索引大小。
  • @TomasKulich 你是正确的计数(*),但优化器是奇怪的野兽,只尝试有限数量的可能访问计划。也许在 Postgresql 中有一条规则,当查询没有任何条件时,则不考虑索引...

标签: postgresql indexing count composite-index query-planner


【解决方案1】:

因为对于像 a=1 这样的条件,不需要重新检查每一行的条件。因此,它只是遍历 b 树并计算所有 a=1 的叶子。在这种情况下不需要引出实际数据。 我会尝试联合使用 a=1 和 a=2 的两个查询,或者像 a

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-09-06
    • 2015-06-10
    • 1970-01-01
    • 1970-01-01
    • 2012-06-20
    • 2011-09-25
    • 2019-03-23
    • 1970-01-01
    相关资源
    最近更新 更多