koflover 发表于 2016-11-22 00:31:20

我对PostgreSQL 中 index scan 与 seq scan 的对比学习

  开始
  数据量很小的时候,我们可以看到,seq scan 比 index scan 更加有效。那是因为 index scan 至少要发生两次I/O,一次是 读取索引块, 一次是读取数据块。当index 很大的时候,情况可能会更加复杂。



postgres=# select a.relpages, a.reltuples, a.relfilenode,a.reltype,b.typname from pg_class a, pg_type b where a.relname like 'gaotab%' and a.reltype=b.oid;   
relpages | reltuples | relfilenode | reltype | typname   
----------+-----------+-------------+---------+---------   
1 |      100 |       16396 |   16386 | gaotab   
  数据量为 100条记录。
  预估成本:



postgres=# set session enable_seqscan=false;                  
SET                  
postgres=# explain select name from gaotab where id=50;                  
QUERY PLAN                                                
---------------------------------------------------------------------                  
Index Scan using idx_id on gaotab(cost=0.00..8.27 rows=1 width=5)                  
Index Cond: (id = 50)                  
(2 rows)                  


postgres=# set session enable_seqscan=true;      
SET      
postgres=# explain select name from gaotab where id=50;      
QUERY PLAN                              
------------------------------------------------------      
Seq Scan on gaotab(cost=0.00..2.25 rows=1 width=5)      
Filter: (id = 50)      
(2 rows)      
  实际执行:



postgres=# set session enable_seqscan=false;      
SET      
postgres=# explain analyze select name from gaotab where id=50;      
QUERY PLAN                           
--------------------------------------------------------------------------------      
-------------------------------      
Index Scan using idx_id on gaotab(cost=0.00..8.27 rows=1 width=5) (actual tim      
e=0.112..0.113 rows=1 loops=1)      
Index Cond: (id = 50)      
Total runtime: 0.133 ms      
(3 rows)      


postgres=# set session enable_seqscan=true;      
SET      
postgres=# explain analyze select name from gaotab where id=50;      
QUERY PLAN                                 
--------------------------------------------------------------------------------      
----------------      
Seq Scan on gaotab(cost=0.00..2.25 rows=1 width=5) (actual time=0.014..0.018         
rows=1 loops=1)      
Filter: (id = 50)      
Rows Removed by Filter: 99      
Total runtime: 0.034 ms      
(4 rows)      
  等到数据量大的时候,就是截然不同了。
  数据为1000条记录时,通过查询可以看到,已经跨越了7个page:



postgres=# analyze;   
ANALYZE   
postgres=# select a.relpages, a.reltuples, a.relfilenode,a.reltype,b.typname from pg_class a, pg_type b where a.relname like 'gaotab%' and a.reltype=b.oid;   
relpages | reltuples | relfilenode | reltype | typname   
----------+-----------+-------------+---------+---------   
7 |      1000 |       16396 |   16386 | gaotab   
(1 row)   
postgres=#   
  再次预估成本,此时seq scan 已经开始变得不划算了:



postgres=# set session enable_seqscan=false;
SET
postgres=# explain select name from gaotab where id=50;
QUERY PLAN                              
---------------------------------------------------------------------
Index Scan using idx_id on gaotab(cost=0.00..8.27 rows=1 width=6)
Index Cond: (id = 50)
(2 rows)
postgres=# set session enable_seqscan=true;
SET
postgres=# explain select name from gaotab where id=50;
QUERY PLAN                              
---------------------------------------------------------------------
Index Scan using idx_id on gaotab(cost=0.00..8.27 rows=1 width=6)
Index Cond: (id = 50)
(2 rows)
postgres=# set session enable_indexscan=false;
SET
postgres=# explain select name from gaotab where id=50;
QUERY PLAN                              
---------------------------------------------------------------------
Bitmap Heap Scan on gaotab(cost=4.26..8.27 rows=1 width=6)
Recheck Cond: (id = 50)
->Bitmap Index Scan on idx_id(cost=0.00..4.26 rows=1 width=0)
Index Cond: (id = 50)
(4 rows)
postgres=# set session enable_bitmapscan=false;
SET
postgres=# explain select name from gaotab where id=50;
QUERY PLAN                     
-------------------------------------------------------
Seq Scan on gaotab(cost=0.00..19.50 rows=1 width=6)
Filter: (id = 50)
(2 rows)
postgres=#
  实际执行



postgres=# set session enable_seqscan=false;
SET
postgres=# explain analyze select name from gaotab where id=50;
QUERY PLAN                                    
------------------------------------------------------------------------------------------------------------
-----------------------
Index Scan using idx_id on gaotab(cost=10000000000.00..10000000008.27 rows=1 width=6) (actual time=0.020.
.0.022 rows=1 loops=1)
Index Cond: (id = 50)
Total runtime: 0.051 ms
(3 rows)
postgres=# set session enable_seqscan=true;
SET
postgres=# set session enable_indexscan=false;
SET
postgres=# set session enable_bitmapscan=false;
SET
postgres=# explain analyze select name from gaotab where id=50;
QUERY PLAN                                          
-------------------------------------------------------------------------------------------------
Seq Scan on gaotab(cost=0.00..19.50 rows=1 width=6) (actual time=0.015..0.095 rows=1 loops=1)
Filter: (id = 50)
Rows Removed by Filter: 999
Total runtime: 0.109 ms
(4 rows)
postgres=#
  [作者:技术者高健@博客园mail: luckyjackgao@gmail.com ]
  结束
页: [1]
查看完整版本: 我对PostgreSQL 中 index scan 与 seq scan 的对比学习