postgresql----Btree索引


當表數據量越來越大時查詢速度會下降,像課本目錄一樣,在表的條件字段上創建索引,查詢時能夠快速定位感興趣的數據所在的位置。索引的好處主要有加速帶條件的查詢,刪除,更新,加速JOIN操作,加速外鍵約束更新和刪除的操作等,但是索引也不是只有好處沒有壞處,創建索引時會鎖表,不僅將數據寫入表中,還要創建索引,因此會在一定程度上影響寫的性能。

 

Btree索引適合處理能夠按順序存儲的數據的=,<,>,<=,>=,以及等效這些操作符的其他操作如BETWEEN,IN以及IS NULL和以字符串開頭的模糊查詢。Btree索引要想起作用where條件必須包含第一個索引列。

 

測試表:

 

test=# create table tbl_index(a bigint,b timestamp without time zone,c varchar(12));
CREATE TABLE
test=# insert into tbl_index (a,b,c)  select generate_series(1,3000000),clock_timestamp()::timestamp(0) without time zone,'got u';
INSERT 0 3000000

 

test=# \timing 
Timing is on.

 

 示例1.創建索引前查詢

 

test=# select * from tbl_index where a=3000000;
    a    |          b          |   c   
---------+---------------------+-------
 3000000 | 2016-06-29 14:54:00 | got u
(1 row)

Time: 303.729 ms

  

創建索引:

test=# create index idx_tbl_index_a on tbl_index using btree(a);
CREATE INDEX
Time: 3743.555 ms

 

示例2.創建索引后查詢

 

test=# select * from tbl_index where a=3000000;
    a    |          b          |   c   
---------+---------------------+-------
 3000000 | 2016-06-29 14:54:00 | got u
(1 row)

Time: 2.316 ms

  

刪除索引

test=# drop index idx_tbl_index_a ;
DROP INDEX

 

創建組合索引

test=# create index idx_tbl_index_a_b on tbl_index using btree(a,b);
CREATE INDEX
Time: 2987.971 ms

 

使用explain命令輸出查詢計划,並使用analyze參數實際執行SQL語句。

示例3.按字段a查詢

test=# explain analyze select * from tbl_index where a=3000000;
                                                          QUERY PLAN                                                          
------------------------------------------------------------------------------------------------------------------------------
 Index Scan using idx_tbl_index_a_b on tbl_index  (cost=0.43..8.45 rows=1 width=22) (actual time=0.026..0.027 rows=1 loops=1)
   Index Cond: (a = 3000000)
 Planning time: 0.127 ms
 Execution time: 0.073 ms
(4 rows)

Time: 1.435 ms

 

示例4.按字段b查詢

test=# explain analyze select * from tbl_index where b='2016-06-29 14:54:00';
                                                            QUERY PLAN                                                             
-----------------------------------------------------------------------------------------------------------------------------------
 Gather  (cost=1000.00..38495.00 rows=171000 width=22) (actual time=306.211..514.992 rows=172824 loops=1)
   Workers Planned: 2
   Workers Launched: 2
   ->  Parallel Seq Scan on tbl_index  (cost=0.00..21107.50 rows=71250 width=22) (actual time=284.671..296.463 rows=57608 loops=3)
         Filter: (b = '2016-06-29 14:54:00'::timestamp without time zone)
         Rows Removed by Filter: 942392
 Planning time: 0.191 ms
 Execution time: 524.130 ms
(8 rows)

Time: 525.623 ms

 

示例5.組合字段查詢 a and b

test=# explain analyze select * from tbl_index where a=3000000 and b='2016-06-29 14:54:00';
                                                          QUERY PLAN                                                          
------------------------------------------------------------------------------------------------------------------------------
 Index Scan using idx_tbl_index_a_b on tbl_index  (cost=0.43..8.45 rows=1 width=22) (actual time=0.031..0.033 rows=1 loops=1)
   Index Cond: ((a = 3000000) AND (b = '2016-06-29 14:54:00'::timestamp without time zone))
 Planning time: 0.169 ms
 Execution time: 0.075 ms
(4 rows)

Time: 1.173 ms

 

示例6.組合字段查詢 a or b

test=# explain analyze select * from tbl_index where a=3000000 or b='2016-06-29 14:54:00';
                                                                    QUERY PLAN                                                       
             
-------------------------------------------------------------------------------------------------------------------------------------
-------------
 Bitmap Heap Scan on tbl_index  (cost=34034.37..41369.38 rows=171001 width=22) (actual time=130.579..145.787 rows=172824 loops=1)
   Recheck Cond: ((a = 3000000) OR (b = '2016-06-29 14:54:00'::timestamp without time zone))
   Heap Blocks: exact=276
   ->  BitmapOr  (cost=34034.37..34034.37 rows=171001 width=0) (actual time=130.480..130.480 rows=0 loops=1)
         ->  Bitmap Index Scan on idx_tbl_index_a_b  (cost=0.00..4.44 rows=1 width=0) (actual time=0.026..0.026 rows=1 loops=1)
               Index Cond: (a = 3000000)
         ->  Bitmap Index Scan on idx_tbl_index_a_b  (cost=0.00..33944.43 rows=171000 width=0) (actual time=130.452..130.452 rows=172
824 loops=1)
               Index Cond: (b = '2016-06-29 14:54:00'::timestamp without time zone)
 Planning time: 0.215 ms
 Execution time: 153.074 ms
(10 rows)

Time: 154.065 ms

 

表中的索引實際是btree(a,b),從以上示例中可以看出,只有where條件包含索引的第一個字段,查詢才會進行索引掃描,否則將進行全表掃描。示例5和示例6比較可知,組合索引字段間使用and和or(測試例使用pg9.6,記得低版本pg組合索引使用or查詢會進行全表掃描,這個不知道是不是記錯了)雖然都是索引掃描,但是and組合要比or組合查詢速度更快。

 

刪除組合索引,然后分別在a和b字段上創建索引

test=# drop index idx_tbl_index_a_b ;
DROP INDEX
Time: 36.017 ms
test=# create index idx_tbl_index_a on tbl_index using btree (a);
CREATE INDEX
Time: 2277.276 ms
test=# create index idx_tbl_index_b on tbl_index using btree (b);
CREATE INDEX
Time: 2278.055 ms

 

分別使用a and b和a or b進行查詢

test=# explain analyze select * from tbl_index where a=3000000 and b='2016-06-29 14:54:00';
                                                         QUERY PLAN                                                         
----------------------------------------------------------------------------------------------------------------------------
 Index Scan using idx_tbl_index_a on tbl_index  (cost=0.43..8.45 rows=1 width=22) (actual time=0.099..0.100 rows=1 loops=1)
   Index Cond: (a = 3000000)
   Filter: (b = '2016-06-29 14:54:00'::timestamp without time zone)
 Planning time: 0.779 ms
 Execution time: 0.137 ms
(5 rows)

Time: 2.154 ms
test=# explain analyze select * from tbl_index where a=3000000 or b='2016-06-29 14:54:00';
                                                                 QUERY PLAN                                                          
        
-------------------------------------------------------------------------------------------------------------------------------------
--------
 Bitmap Heap Scan on tbl_index  (cost=1840.87..9175.88 rows=171001 width=22) (actual time=29.026..48.537 rows=172824 loops=1)
   Recheck Cond: ((a = 3000000) OR (b = '2016-06-29 14:54:00'::timestamp without time zone))
   Heap Blocks: exact=276
   ->  BitmapOr  (cost=1840.87..1840.87 rows=171001 width=0) (actual time=28.968..28.968 rows=0 loops=1)
         ->  Bitmap Index Scan on idx_tbl_index_a  (cost=0.00..4.44 rows=1 width=0) (actual time=0.022..0.022 rows=1 loops=1)
               Index Cond: (a = 3000000)
         ->  Bitmap Index Scan on idx_tbl_index_b  (cost=0.00..1750.93 rows=171000 width=0) (actual time=28.943..28.943 rows=172824 l
oops=1)
               Index Cond: (b = '2016-06-29 14:54:00'::timestamp without time zone)
 Planning time: 0.142 ms
 Execution time: 57.446 ms
(10 rows)

Time: 58.151 ms

 

結果顯示分別在a和b字段上創建索引與在(a,b)組合字段上創建索引相比,and查詢性能下降,但是or的性能可以提升。

 

PS:主鍵和唯一鍵會自動創建Btree索引,無需另外單獨再為主鍵和唯一鍵創建索引。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM