接上篇《构建一个完整的数据仓库(十)doris的数据模型》。上一篇我们介绍了doris创建表的时候需要使用的数据模型,基于数据模型,我们可以普适对应的业务。那么有了数据模型,我们肯定是需要进行查询的,所以这一篇我们来介绍下doris的索引信息。
重要说明:
在doris中,他和mysql一样也是支持索引的,只是他的索引和mysql区别还是挺大,在使用上还得注意一下。doris支持的索引类型有:
1、内建的智能索引(包括:前缀索引和ZoneMap索引) 2、创建的二级索引(包括Bloom Filter索引和Bitmap倒排索引)
下面我们挨个来介绍一下。
一、前缀索引
前缀索引是doris默认就创建好了的,我们在业务中可以直接使用,那么什么是前缀索引呢?前缀索引打个比方就类似mysql的最左侧匹配。前缀索引在官方的文档介绍里面是这样子的:
本质上,Doris 的数据存储在类似 SSTable(Sorted String Table)的数据结构中。该结构是一种有序的数据结构,可以按照指定的列进行排序存储。在这种数据结构上,以排序列作为条件进行查找,会非常的高效。 而前缀索引,即在排序的基础上,实现的一种根据给定前缀列,快速查询数据的索引方式。 前缀索引是以Block为粒度创建的稀疏索引,一个Block包含1024行数据,每个Block,以该Block的第一行数据的前缀列的值作为索引。
说的直白一点,就是这个前缀索引和创建表的时候放的字段位置相关,一般从第0个开始,我们写where条件的时候也从第0个开始。举个例子,我们有一张user表:
CREATE TABLE `user` ( `userid` bigint(20) NULL COMMENT "", `username` varchar(20) NULL COMMENT "", `usercost` decimal(8, 2) NULL COMMENT "", `costdate` datetime NULL COMMENT "" ) ENGINE=OLAP UNIQUE KEY(`userid`) COMMENT "OLAP" DISTRIBUTED BY HASH(`userid`) BUCKETS 1 PROPERTIES ( "replication_allocation" = "tag.location.default: 1", "in_memory" = "false", "storage_format" = "V2" )
如果我们的查询语句是这样子的: select * from user where userid = 1 这时候就会自动命中前缀索引
如果我们的查询语句是这样子的: select * from user where userid = 1 and username = '张三' 这时候也会自动命中前缀索引
如果我们的查询语句是这样子的: select * from user where username = '张三' 这时候就不会自动命中前缀索引
如果我们的查询语句是这样子的: select * from user where userid = 1 and usercost = 2.70 这时候只会命中userid = 1的索引
从上面的例子来看,where条件后面的字段顺序需要和创建表的时候的字段顺序保持一致。所以我们在进行业务处理的时候,在创建表的阶段我们就要考虑下后续的查询具体是什么情况。
有人会问,那么我们使用
select * from user where userid = 1 and username = '张三' and usercost = 2.70
会不会命中索引呢?这样其实也是会命中索引的,只是这时候索引只到username这一个字段。这里就给大家介绍下doris前缀索引的规则。doris的前缀索引会自动判断字段类型的字节数,取前36个字节作为索引。从前往后数,遇到 VARCHAR 类型时,前缀索引会直接截断。
举个例子:
1、有一张表的字段是:user_id(bigint)+ age(int)+ message(varchar(100))+max_dwell_time(datetime)+min_dwell_time(datetime)5个字段组成,这时候的有效前缀索引是:user_id(8Byte) + age(4Bytes) + message(prefix 20 Bytes)
2、有一张表的字段是:user_name(varchar(100))+ age(int)+ message(varchar(100))+max_dwell_time(datetime)+min_dwell_time(datetime)5个字段组成,这时候的有效前缀索引是:user_name(prefix 36 Bytes)。
看到了吧,遇到varchar会自动截断,如果不满足36个字节,则继续往下数就可以了。
二、Bloom Filter 索引
官方的介绍是:
原理 用户可以在建表时指定在某些列上创建Bloom Filter索引(以下简称BF索引)。也可以在运行时通过 ALTER TABLE 命令新增BF索引。 Bloom Filter本质上是一种位图结构,用于快速的判断一个给定的值是否在一个集合中。这种判断会产生小概率的误判。即如果返回 False,则一定不在这个集合内。而如果范围 True,则有可能在这个集合内。 BF索引也是以Block为粒度创建的。每个Block中,指定列的值作为一个集合生成一个BF索引条目,用于在查询是快速过滤不满足条件的数据。
一般我们在判断是否存在某些值得时候,会在创建表或者使用的时候alter表,给添加一份bloom filter。创建表的时候添加Bloom Filter索引的示例是:
CREATE TABLE IF NOT EXISTS sale_detail_bloom ( sale_date date NOT NULL COMMENT "销售时间", customer_id int NOT NULL COMMENT "客户编号", saler_id int NOT NULL COMMENT "销售员", sku_id int NOT NULL COMMENT "商品编号", category_id int NOT NULL COMMENT "商品分类", sale_count int NOT NULL COMMENT "销售数量", sale_price DECIMAL(12,2) NOT NULL COMMENT "单价", sale_amt DECIMAL(20,2) COMMENT "销售总金额") Duplicate KEY(sale_date, customer_id,saler_id,sku_id,category_id) PARTITION BY RANGE(sale_date) (PARTITION P_202111 VALUES [('2021-11-01'), ('2021-12-01'))) DISTRIBUTED BY HASH(saler_id) BUCKETS 10 PROPERTIES ( "replication_num" = "3", "bloom_filter_columns"="saler_id,category_id", "dynamic_partition.enable" = "true", "dynamic_partition.time_unit" = "MONTH", "dynamic_partition.time_zone" = "Asia/Shanghai", "dynamic_partition.start" = "-2147483648", "dynamic_partition.end" = "2", "dynamic_partition.prefix" = "P_", "dynamic_partition.replication_num" = "3", "dynamic_partition.buckets" = "3" );
这个bloom filter是在properties里面添加的,指定对应的列。
查看Bloom Filter的命令是:
SHOW CREATE TABLE <table_name>
删除Bloom Filter的命令是:
ALTER TABLE <db.table_name> SET ("bloom_filter_columns" = "");
修改Bloom Filter的命令是:
ALTER TABLE <db.table_name> SET ("bloom_filter_columns" = "k1,k3");
Doris BloomFilter使用场景
满足以下几个条件时可以考虑对某列建立Bloom Filter 索引: 首先BloomFilter适用于非前缀过滤. 查询会根据该列高频过滤,而且查询条件大多是in和 = 过滤. 不同于Bitmap, BloomFilter适用于高基数列。比如UserID。因为如果创建在低基数的列上,比如”性别“列,则每个Block几乎都会包含所有取值,导致BloomFilter索引失去意义
Doris BloomFilter使用注意事项
不支持对Tinyint、Float、Double 类型的列建Bloom Filter索引。 Bloom Filter索引只对in和 = 过滤查询有加速效果。 如果要查看某个查询是否命中了Bloom Filter索引,可以通过查询的Profile信息查看
三、Bitmap 索引
官方的介绍是:
用户可以在建表时指定在某些列上创建Bitmap索引。也可以在运行时通过 [ALTER TABLE](TODO) 命令新增Bitmap索引。 Bitmap索引是一种特殊的数据库索引技术,其索引使用bit数组(或称bitmap、bit set、bit string、bit vector)进行存储与计算操作。位置编码中的每一位表示键值对应的数据行的有无。一个位图可能指向的是几十甚至成百上千行数据的位置。 这种方式存储数据,相对于 B*Tree 索引,占用的空间非常小,创建和使用非常快。当根据键值查询时,可以根据Bitmap索引快速定位到具体的行号。而当根据键值做 and/or 或 in(x,y,..) 查询时,直接用索引的位图进行或运算,快速得出结果行数据。
创建bitmap索引的命令是:
ADD INDEX [IF NOT EXISTS] index_name (column [, ...],) [USING BITMAP] [COMMENT 'balabala'];
查看bitmap索引的命令是:
show index ROM <table_name>;
删除bitmap索引的命令是:
DROP INDEX [IF EXISTS] index_name;
bitmap支持的数据类型有:
TINYINT SMALLINT INT UNSIGNEDINT BIGINT CHAR VARCHAR DATE DATETIME LARGEINT DECIMAL BOOL
关于bitmap索引的注意事项
1、bitmap索引只针对与单列,也就是只能在单列上创建。这里打个比方,user表中,我们可以在userid和userphoneno字段上创建2bitmap索引,不能在userid和userphoneno字段创建一个索引(mysql的联合索引效果) 2、bitmap索引适用于高基数,不适用于低基数,例如用户表,我们在这里一般会在userid上创建bitmap索引而不会在usersex上创建bitmap索引。 3、bitmap索引一般使用在in或者=的条件中。 4、bitmap在多条件过滤的查询语句里面有显著效果
还没有评论,来说两句吧...