postgresql-扫描方式

Pg中支持的扫描方式

  1. 顺序扫描
  2. 索引扫描
  3. 仅索引扫描
  4. 位图扫描
  5. tid扫描

试验

建表
postgres=# create table abce(id int, num numeric);
CREATE TABLE
postgres=# create index idx_abce on abce(num);
CREATE INDEX
postgres=# insert into abce select generate_series(1,1000000),random()*1000;
INSERT 0 1000000
postgres=# analyze;
ANALYZE
seq scan
postgres=# explain select * from abce where num < 20000;
                          QUERY PLAN                          
---------------------------------------------------------------
 Seq Scan on abce  (cost=0.00..17990.00 rows=1000000 width=15)
   Filter: (num < '20000'::numeric)
(2 rows)
index scan
postgres=# explain select * from abce where num = 20000;
                              QUERY PLAN                             
----------------------------------------------------------------------
 Index Scan using idx_abce on abce  (cost=0.42..8.44 rows=1 width=15)
   Index Cond: (num = '20000'::numeric)
(2 rows)
 
postgres=#
Index Only Scan
postgres=# explain select num from abce where num = 20000;
                                QUERY PLAN                                
---------------------------------------------------------------------------
 Index Only Scan using idx_abce on abce  (cost=0.42..8.44 rows=1 width=11)
   Index Cond: (num = '20000'::numeric)
(2 rows)
 
postgres=#
Bitmap Scan

如果选择少量的行,索引扫描,如果大部分的行,将读取全表;如果对于索引扫描来说读取太多,而顺序扫描来说太少,就会使用位图扫描

原理是扫描过程中,单个块只使用一次。

(1) 位图索引扫描:

首先从索引数据结构中获取所有索引数据,并创建所有TID的位图。为了简单理解,可以认为此位图包含所有页的哈希值(基于page no哈希),每个页面条目包含该页面中所有偏移量的数组。

(2) 位图堆扫描:

顾名思义,它读取页的位图,然后扫描与存储页和偏移量对应的堆中的数据。最后,它检查可见性和谓词等,并根据所有这些检查的结果返回元组。

postgres=# explain select * from abce where num < 200;
                                  QUERY PLAN                                  
-------------------------------------------------------------------------------
 Bitmap Heap Scan on abce  (cost=5468.94..13430.74 rows=197744 width=15)
   Recheck Cond: (num < '200'::numeric)
   ->  Bitmap Index Scan on idx_abce  (cost=0.00..5419.51 rows=197744 width=0)
         Index Cond: (num < '200'::numeric)
(4 rows)
Tid Scan
postgres=# select ctid from abce where id=20000;
   ctid   
-----------
 (109,143)
(1 row)
 
postgres=# explain select * from abce where ctid='(109,143)';
                     QUERY PLAN                     
-----------------------------------------------------
 Tid Scan on abce  (cost=0.00..4.01 rows=1 width=15)
   TID Cond: (ctid = '(109,143)'::tid)
(2 rows)
posted @ 2021-08-29 16:56  y_dou  阅读(269)  评论(0)    收藏  举报