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

问题描述 投票:2回答:1

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

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)
postgresql
1个回答
5
投票

创建一个页面表:

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

seq扫描:

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)

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

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

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

这里2表示第二页(从零开始计数)。

或者从冗长的计划中再次:

db=# set enable_indexonlyscan to off;
SET
db=# set enable_indexscan to off;
SET    
db=# set enable_bitmapscan to off;
SET
db=# explain (analyze, verbose, buffers) select g from small where g = 200;
                                              QUERY PLAN
------------------------------------------------------------------------------------------------------
 Seq Scan on public.small  (cost=0.00..9.25 rows=1 width=4) (actual time=0.124..0.303 rows=1 loops=1)
   Output: g
   Filter: (small.g = 200)
   Rows Removed by Filter: 499
   Buffers: shared hit=3
 Planning time: 0.105 ms
 Execution time: 0.327 ms
(7 rows)

在这里,命中= 3

© www.soinside.com 2019 - 2024. All rights reserved.