KingbaseES 局部索引

一个列要不要建立btree索引,判断条件是其键值分布是否够离散,比如主键、唯一键,可以建立索引。如果这个列有大量重复的值,则建立索引没有意义。

在生产环境中常会碰到键值分布不均匀的列,如表t1有一个名为FLAG的列,有0,1,2三个值,其中值为0的记录占95%,值为1的占3%,2占2%。在FLAG上建立索引,搜索FLAG=1或2可利用到此索引,而搜索FLAG=0 则因有大量的重复值而利用不到此索引。也就是说此索引有95%的内容是无效的,白白浪费了存储等资源。

KingbaseES有种索引,叫Partial Index(局部索引)可以很好的解决以上问题。
1 什么是partial index
局部索引是基于表中部分数据建立的,被索引的部分数据是原数据的一个子集。这个子集数据是基于某些条件可以明确计算出来的。
2 partial index适用场景
对于表中数据分布“不均匀”的场景,比如某些数据占据绝大多数,而其它一些数据只占少量,且要满足查询条件针是对那些小数据量的查询情形。
通过partial index可以排除大量普通数据或业务上“不感兴趣”的数据。
3 partial index的优势
由于其是针对部分数据进行索引,显然同传统b-tree索引相比,其所占磁盘空间将大大缩小。当重建维护这些分区索引时,速度也非常快。

test=# create table t_pindex(id int,name varchar(30));
CREATE TABLE
test=# insert into t_pindex select generate_series(1,2000),'AAA';
INSERT 0 2000
test=# insert into t_pindex select generate_series(2001,2050),'BBB';
INSERT 0 50
test=# create index idx_pindex on t_pindex(name) where name != 'AAA';
CREATE INDEX
test=# create index idx_full on t_pindex(name);
CREATE INDEX
test=# analyze t_pindex;

在本例子中AAA值占比超过95%,所以即使列上有索引也不会使用索引扫描
test=# explain analyze select * from t_pindex where name = 'AAA';
                                                QUERY PLAN                                                
----------------------------------------------------------------------------------------------------------
 Seq Scan on t_pindex  (cost=0.00..35.62 rows=2000 width=8) (actual time=0.036..18.522 rows=2000 loops=1)
   Filter: ((name)::text = 'AAA'::text)
   Rows Removed by Filter: 50
 Planning Time: 0.266 ms
 Execution Time: 35.368 ms
(5 行记录)

局部索引的存储空间比普通索引的存储空间要小。
test=# \di+ idx_full
关联列表
-[ RECORD 1 ]------
架构模式 | public
名称     | idx_full
类型     | 索引
拥有者   | system
数据表   | t_pindex
大小     | 64 kB
描述     | 

test=# \di+ idx_pindex
关联列表
-[ RECORD 1 ]--------
架构模式 | public
名称     | idx_pindex
类型     | 索引
拥有者   | system
数据表   | t_pindex
大小     | 16 kB
描述     | 

使用hint指定查询时使用的索引,可以看出局部索引的查询效率会高于普通的索引。
test=# explain analyze select   /*+ indexscan(a idx_pindex) */ * from t_pindex a  where name = 'BBB';                    
                                                        QUERY PLAN                                                        
--------------------------------------------------------------------------------------------------------------------------
 Index Scan using idx_pindex on t_pindex a  (cost=0.14..13.02 rows=50 width=8) (actual time=0.025..0.392 rows=50 loops=1)
   Index Cond: ((name)::text = 'BBB'::text)
 Planning Time: 0.084 ms
 Execution Time: 0.785 ms
(4 行记录)

test=# explain analyze select  /*+ indexscan(a idx_full) */ * from t_pindex a  where name = 'BBB'; 
                                                      QUERY PLAN                                                       
-----------------------------------------------------------------------------------------------------------------------
 Index Scan using idx_full on t_pindex a  (cost=0.28..9.15 rows=50 width=8) (actual time=0.060..0.668 rows=50 loops=1)
   Index Cond: ((name)::text = 'BBB'::text)
 Planning Time: 0.154 ms
 Execution Time: 1.760 ms
(4 行记录)
posted @ 2022-09-03 09:11  KINGBASE研究院  阅读(126)  评论(0编辑  收藏  举报