zoukankan      html  css  js  c++  java
  • 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=# 	iming 
    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索引,无需另外单独再为主键和唯一键创建索引。

  • 相关阅读:
    Jenkins:自动生成iOS包遇到的问题
    Jenkins将构建结果发送至钉钉群的实现
    Selenium常见API
    Jenkins配置Maven工程
    Appium多设备并行
    使用Docker安装MySQL
    Selenium无界面执行
    mysql 进阶查询(学习笔记)
    xshell 常用命令
    mysql 常用语句
  • 原文地址:https://www.cnblogs.com/alianbog/p/5621749.html
Copyright © 2011-2022 走看看