为什么postgres会扫描所有表格?

时间:2018-06-29 23:33:12

标签: postgresql

我发现对索引列执行的查询会导致顺序扫描:

mydatabase=> explain analyze SELECT account_id,num_tokens,tok_holdings FROM tokacct WHERE address='00000000000000000';
                                            QUERY PLAN                                            
--------------------------------------------------------------------------------------------------
 Seq Scan on tokacct  (cost=0.00..6.69 rows=1 width=27) (actual time=0.046..0.046 rows=0 loops=1)
   Filter: (address = '00000000000000000'::text)
   Rows Removed by Filter: 225
 Planning time: 0.108 ms
 Execution time: 0.075 ms
(5 rows)

mydatabase=> 

但是\di显示我有一个唯一索引:

mydatabase=> \di
                         List of relations
 Schema |          Name           | Type  | Owner  |     Table      
--------+-------------------------+-------+--------+----------------
......
 public | tokacct_address_key     | index | mydb   | tokacct
.....

我的表是这样定义的:

CREATE TABLE tokacct (
        tx_id                           BIGINT                  NOT NULL,
        account_id                      SERIAL                  PRIMARY KEY,
        state_acct_id                   INT                     NOT NULL DEFAULT 0,        
        num_tokens                      INT                     DEFAULT 0,
        ts_created                      INT                     DEFAULT 0,
        block_created           INT                             DEFAULT 0,
        address                         TEXT                    NOT NULL UNIQUE
        tok_holdings                    TEXT                    DEFAULT ''                      
);

如您所见,address字段被声明为UNIQUE\di还确认存在索引。那么,为什么在表上使用顺序扫描呢?

Seq Scan on tokacct  (cost=0.00..6.69 rows=1 width=27) (actual time=0.046..0.046 rows=0 loops=1)

1 个答案:

答案 0 :(得分:5)

创建一页表格:

[0, 1, 1, 2, 3, 5, 8, 13]

序列扫描:

db=# create table small as select g, chr(g) from generate_series(1,200) g;
SELECT 200
db=# create index small_i on small(g);
CREATE INDEX
db=# analyze small;
ANALYZE

创建三页表:

db=# explain (analyze, verbose, buffers) select g from small where g = 200;
                                              QUERY PLAN
------------------------------------------------------------------------------------------------------
 Seq Scan on public.small  (cost=0.00..3.50 rows=1 width=4) (actual time=0.044..0.045 rows=1 loops=1)
   Output: g
   Filter: (small.g = 200)
   Rows Removed by Filter: 199
   Buffers: shared hit=1
 Planning time: 1.360 ms
 Execution time: 0.066 ms
(7 rows)

现在该表需要三个页面和两个索引,因此索引更便宜...

我怎么知道页数?它在(详细的)执行计划中是这样说的。和桌子?

db=# drop table small;
DROP TABLE
db=# create table small as select g, chr(g) from generate_series(1,500) g;
SELECT 500
db=# create index small_i on small(g);
CREATE INDEX
db=# analyze small;
ANALYZE
db=# explain (analyze, verbose, buffers) select g from small where g = 200;
                                                        QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------
 Index Only Scan using small_i on public.small  (cost=0.27..8.29 rows=1 width=4) (actual time=3.194..3.195 rows=1 loops=1)
   Output: g
   Index Cond: (small.g = 200)
   Heap Fetches: 1
   Buffers: shared hit=1 read=2
 Planning time: 0.271 ms
 Execution time: 3.747 ms
(7 rows)

此处 2 表示第二页(从零开始计数)。

或再次从详细计划中获取:

db=# select max(ctid) from small;
  max
--------
 (2,48)
(1 row)

在这里, hit = 3