为啥索引扫描应该只检索两行?

Posted

技术标签:

【中文标题】为啥索引扫描应该只检索两行?【英文标题】:Why does an index scan retrieve two rows when there should only be one?为什么索引扫描应该只检索两行? 【发布时间】:2020-01-15 20:05:55 【问题描述】:

在修补pgbenchEXPLAIN 时,我发现了以下内容:

[root@fc26c91163dc /]# pgbench -i
100000 of 100000 tuples (100%) done (elapsed 0.21 s, remaining 0.00 s)
vacuuming...
creating primary keys...
done.
[root@fc26c91163dc /]# psql
psql (12.1)
Type "help" for help.

postgres=# insert into pgbench_branches values (generate_series(2,100000),1,'');
INSERT 0 99999
postgres=# vacuum full analyze;
VACUUM
postgres=# EXPLAIN ANALYZE SELECT * FROM pgbench_accounts a JOIN pgbench_branches b ON (a.bid=b.bid) WHERE a.aid < 100;
                                                                        QUERY PLAN                                                                         
-----------------------------------------------------------------------------------------------------------------------------------------------------------
 Merge Join  (cost=15.01..16.64 rows=106 width=194) (actual time=0.114..0.323 rows=99 loops=1)
   Merge Cond: (b.bid = a.bid)
   ->  Index Scan using pgbench_branches_pkey on pgbench_branches b  (cost=0.29..4247.29 rows=100000 width=97) (actual time=0.013..0.016 rows=2 loops=1)
   ->  Sort  (cost=14.71..14.98 rows=106 width=97) (actual time=0.091..0.098 rows=99 loops=1)
         Sort Key: a.bid
         Sort Method: quicksort  Memory: 38kB
         ->  Index Scan using pgbench_accounts_pkey on pgbench_accounts a  (cost=0.29..11.15 rows=106 width=97) (actual time=0.008..0.038 rows=99 loops=1)
               Index Cond: (aid < 100)
 Planning Time: 0.690 ms
 Execution Time: 0.380 ms
(10 rows)

通知Index Scan using pgbench_branches_pkey...actual time=0.013..0.016 rows=2...

pgbench_accounts 中只有一个不同的 bid 值:

postgres=# select distinct bid from pgbench_accounts ;
 bid 
-----
   1
(1 row)

bidpgbench_branches 中的主键:

postgres=# select * from pgbench_branches where bid = 1;
 bid | bbalance | filler 
-----+----------+--------
   1 |        0 | 
(1 row)

那么为什么Index Scan 产生rows=2 而不是rows=1

【问题讨论】:

【参考方案1】:

它不知道 pgbench_branches 中存在的下一行的出价>1,直到它读取下一行并看到它的出价>1。它可能能够从主键约束中推断出它,但它并不是为此而编写的。

【讨论】:

谢谢!这完全有道理

以上是关于为啥索引扫描应该只检索两行?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 oracle 表索引但仍然进行全表扫描?

为啥 oracle 对此查询使用索引跳过扫描?

SQL 数据优化索引建suo避免全表扫描

SQL 数据优化索引建suo避免全表扫描

为啥这是索引扫描而不是索引查找

为啥 PostgreSQL 对索引列执行顺序扫描?