MergeTree中clickhouse稀疏索引怎么用

发布时间:2021-12-10 11:39:02 作者:小新
来源:亿速云 阅读:305

这篇文章主要为大家展示了“MergeTree中clickhouse稀疏索引怎么用”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“MergeTree中clickhouse稀疏索引怎么用”这篇文章吧。

MergeTree存储结构逻辑示意图

MergeTree中clickhouse稀疏索引怎么用

MergeTree表的存储结构中,每个数据分区相互独立,逻辑上没有关联。单个数据分区内部存在着多个MergeTree Data Part。这些Data Part一旦生成就是Immutable的状态,Data Part的生成和销毁主要与写入和异步Merge有关。MergeTree表的写入链路是一个极端的batch load过程,Data Part不支持单条的append insert。每次batch insert都会生成一个新的MergeTree Data Part。如果用户单次insert一条记录,那就会为那一条记录生成一个独立的Data Part,这必然是无法接受的。一般我们使用MergeTree表引擎的时候,需要在客户端做聚合进行batch写入。

1、概念

mark numbervalue
0a
1a
2b

MergeTree中clickhouse稀疏索引怎么用

索引中的mark index压缩数据index在压缩数据块中起始的字节数(偏移量)
000
1012001
210

2、数据存储

文件目录

MergeTree中clickhouse稀疏索引怎么用

action_id.bin、avatar_id.bin等都是单个列按块压缩后的列存文件

Mark标识文件:action_id.mrk2、avatar_id.mrk2等都是列存文件中的Mark标记,Mark标记和MergeTree列存中的两个重要概念相关:Granule和Block。

主键索引:primary.idx是表的主键索引。ClickHouse对主键索引的定义和传统数据库的定义稍有不同,它的主键索引没用主键去重的含义,但仍然有快速查找主键行的能力。ClickHouse的主键索引存储的是每一个Granule中起始行的主键值,而MergeTree存储中的数据是按照主键严格排序的。所以当查询给定主键条件时,我们可以根据主键索引确定数据可能存在的 ,再结合上面介绍的Mark标识,我们可以进一步确定数据在列存文件中的位置区间。ClickHoue的主键索引是一种在索引构建成本和索引效率上相对平衡的粗糙索引。MergeTree的主键序列默认是和Order By序列保存一致的,但是用户可以把主键序列定义成Order By序列的部分前缀。

分区键索引:minmax_time.idx、minmax_region_name.idx是表的分区键索引。MergeTree存储会把统计每个Data Part中分区键的最大值和最小值,当用户查询中包含分区键条件时,就可以直接排除掉不相关的Data Part,这是一种OLAP场景下常用的分区裁剪技术。

Skipping索引:skp_idx_avatar_id_minmax.idx是用户在avatar_id列上定义的MinMax索引。Merge Tree中 的Skipping Index是一类局部聚合的粗糙索引。用户在定义skipping index的时候需要设定granularity参数,这里的granularity参数指定的是在多少个Granule的数据上做聚合生成索引信息。用户还需要设定索引对应的聚合函数,常用的有minmax、set、bloom_filter、ngrambf_v1等,聚合函数会统计连续若干个Granule中的列值生成索引信息。Skipping索引的思想和主键索引是类似的,因为数据是按主键排序的,主键索引统计的其实就是每个Granule粒度的主键序列MinMax值,而Skipping索引提供的聚合函数种类更加丰富,是主键索引的一种补充能力。另外这两种索引都是需要用户在理解索引原理的基础上贴合自己的业务场景来进行设计的。

3、检索过程

MergeTree存储在收到一个select查询时会先抽取出查询中的分区键和主键条件的KeyCondition,KeyCondition类上实现了以下三个方法,用于判断过滤条件可能满足的Mark Range。上面讲过MergeTree Data Part中的列存数据是以Granule为粒度被Mark标识数组索引起来的,而Mark Range就表示Mark标识数组里满足查询条件的下标区间。

索引检索的过程中首先会用分区键KeyCondition裁剪掉不相关的数据分区,然后用主键索引挑选出粗糙的Mark Range,最后再用Skipping Index过滤主键索引产生的Mark Range。用主键索引挑选出粗糙的Mark Range的算法是一个不断分裂Mark Range的过程,返回结果是一个Mark Range的集合。起始的Mark Range是覆盖整个MergeTree Data Part区间的,每次分裂都会把上次分裂后的Mark Range取出来按一定粒度步长分裂成更细粒度的Mark Range,然后排除掉分裂结果中一定不满足条件的Mark Range,最后Mark Range到一定粒度时停止分裂。这是一个简单高效的粗糙过滤算法。

使用Skipping Index过滤主键索引返回的Mark Range之前,需要构造出每个Skipping Index的IndexCondition,不同的Skipping Index聚合函数有不同的IndexCondition实现,但判断Mark Range是否满足条件的接口和KeyCondition是类似的。

数据Sampling

经过上一小节的索引过滤之后,我们已经得到了需要扫描的Mark Range集合,接下来就应该是数据扫描部分了。这一小节插入简单讲一下MergeTree里的数据Sampling是如何实现的。它并不是在数据扫描过程中实现的,而是在索引检索的过程中就已经完成,这种做法是为了极致的sample效率。用户在建表的时候可以指定主键中的某个列或者表达式作为Sampling键,ClickHouse在这里用了简单粗暴的做法:Sampling键的值必须是数值类型的,并且系统假定它的值是随机均匀分布的一个状态。如果Sampling键的值类型是Uint32,当我们设定sample比率是0.1的时候,索引检索过程中会把sample转换成一个filter条件:Sampling键的值 < Uint32::max * 0.1。用户在使用Sampling功能时必须清楚这个细节,不然容易出现采样偏差。一般我们推荐Sampling键是列值加一个Hash函数进行随机打散。

数据扫描

MergeTree的数据扫描部分提供了三种不同的模式:

接下来展开介绍下Normal模式中几个关键的性能优化点:

以上是“MergeTree中clickhouse稀疏索引怎么用”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注亿速云行业资讯频道!

推荐阅读:
  1. MongoDB中索引怎么用
  2. MySQL中覆盖索引怎么用

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

clickhouse

上一篇:Hadoop机架感知及启动停止方法是什么

下一篇:Hive函数怎么用

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》