postgresql - 多列索引不用于仅索引扫描,但部分索引是

标签 postgresql sql-execution-plan postgres-9.6

我的问题是为什么多列索引不用于仅索引扫描,而具有等效信息(我认为)的部分索引是。

表格:

CREATE TABLE test 
(
  id      INT,
  descr   TEXT,
  flag    BOOLEAN
);

INSERT INTO test
SELECT GENERATE_SERIES(1,100000) AS id,
       MD5(RANDOM()::TEXT) AS descr,
       (RANDOM() < 0.1) AS flag;

SELECT *
FROM test LIMIT 10;

内容示例:

id  descr   flag
1   81978ceb5514461fbad9af1152ad78f6    true
2   cc0aee68ba3e0095cc74d53e8da55fef    false
3   689a76e5897d565638f8ddd2d2019b7a    true
4   9df03bc2969a6af88cd1d6e0423d0f4c    true
5   318983766d11f831e9f0df34606dc908    false
6   198102bb71640a16f28263b7fb56ba2e    false
7   9bef7320389db46a8ad88ffa611e81b5    false
8   c1f0d637ee0a985aa7d768a78d2d97b1    false
9   781b4064f721ae3879d95579264b0aba    false
10  c4582890bb1e9af430e0f36b50f5e88c    false

我需要运行的查询是:

SELECT id
FROM test
WHERE flag;

现在如果我使用部分索引。查询(最终)作为仅索引扫描执行:

CREATE INDEX i1 
  ON test (id) WHERE flag;

QUERY PLAN
Index Only Scan using i1 on test  (cost=0.29..354.95 rows=9911 width=4) (actual time=0.120..6.268 rows=9911 loops=1)
  Heap Fetches: 9911
  Buffers: shared hit=834 read=29
Planning time: 0.806 ms
Execution time: 6.922 ms

我不明白的是:为什么以下形式的多列索引从不用于仅索引扫描?

CREATE INDEX i2 
  ON test (flag, id);

QUERY PLAN
Bitmap Heap Scan on test  (cost=189.10..1122.21 rows=9911 width=4) (actual time=0.767..5.986 rows=9911 loops=1)
  Filter: flag
  Heap Blocks: exact=834
  Buffers: shared hit=863
  ->  Bitmap Index Scan on i2  (cost=0.00..186.62 rows=9911 width=0) (actual time=0.669..0.669 rows=9911 loops=1)
        Index Cond: (flag = true)
        Buffers: shared hit=29
Planning time: 0.090 ms
Execution time: 6.677 ms

查询不能访问标志为 True 的 btree 的所有连续叶子以确定所有 ID 吗?

(请注意,元组可见性可能不是问题,因为仅索引扫描与部分索引 i1 一起使用。)

我的 Postgres 版本是:PostgreSQL 9.6.2 on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 5.3.1-14ubuntu2) 5.3.1 20160413, 64-bit

最佳答案

无法确定系统行为的确切原因,这可能是由误导 PostgreSQL 优化器的错误统计信息或不准确的可见性映射引起的。

VACUUM (ANALYZE) test;

会做两件事:

  1. 它将更新可见性 map ,这是 PostgreSQL 做出明智决定是否可以执行仅索引扫描所必需的。

  2. 它会收集表的统计信息,使 PostgreSQL 准确估计结果行数,从而选择最佳计划。

关于postgresql - 多列索引不用于仅索引扫描,但部分索引是,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51425724/

相关文章:

c# - npgsql/PostgreSQL 在 LAN 上的性能非常低

postgresql - Postgres 9.6 - jsonb 列中特定字段的平均值,并按同一 jsonb 列上的另一个字段进行分组

mysql - 当列上存在键时,为什么索引不用于 Group by 和/或 Join

sql - 如何链接两个表,但只从 PostgreSQL 中的一个表中获取 MAX 值?

mysql - psql 查询中的点表示法 - 有什么区别?

java - 使用 JOOQ 更新 PostgreSQL 中的 jsonb 值

sql - 我如何获得以下 postgres 查询?

java - 如何从匿名 PL/pgSQL block 返回结果?

postgresql - 定义函数的 session 级别估计

sql-server - SQL Server执行计划: filter to show bottlenecks?