clickhouse布隆过滤器跳数索引最佳实践

背景

本文来聊一下clickhouse的这个列式存储数据库的布隆过滤器的跳数索引类型,来了解它的数据结构,它可以为那些查询类型提供查询优化。

跳数索引-布隆过滤器

首先布隆过滤器家族的跳数索引分成三种类型: ngrambf_v1,tokenbf_v1,bloom_filter其原理是类似的,都是基于布隆过滤器数组来过滤数据,我们先看一下他们的数据结构:
clickhouse布隆过滤器跳数索引最佳实践_第1张图片
我们重点讲讲tokenbf_v1和ngrambf_v1这两类跳数索引,这两类跳数索引都是作用于字符串类型:String,FixString上的。
1.tokenbf_v1跳数索引先把字符串的列按照空格等分解成一个个token字符串的形式,然后对这些token集合构建布隆过滤器,我们知道布隆过滤器存在假阳性的问题,也就是虽然布隆过滤器判断包含某个字符串,但是实际上这个字符串并不存在这一列的数据中.所以这个跳数索引只支持如下类型的查询优化

s LIKE '%test%'
NOT s NOT LIKE '%test%'
s = 1
NOT s != 1
startsWith(s, 'test')
endWith(s,'test')
s in ('test','test1')

不支持返回结果预期为false的查询优化

NOT s LIKE '%test%'
s NOT LIKE '%test%'
NOT s = 1
s != 1
NOT startsWith(s, 'test')
NOT endWith(s,'test')
NOT s in ('test','test1')

这里我们可以看出跳数索引是支持模糊查询也就是带%通配符的查询优化的,比如它会先去查找test这个字符在布隆过滤器中是否存在,如果不存在,就可以跳过这些数据块的扫描了.
2.ngrambf_v1类型的跳数索引先把字符串的列按照固定的N个字符的形式把字符串分解成一个个token字符串的形式,然后对这些token集合构建布隆过滤器,这个跳数索引支持和tokenbf_v1一样的查询优化,唯一要注意的比如这个ngrambf_v1使用N=4个字符分割字符串,那么对于s like '%tes%' 这种常量的长度小于4的查询是没法使用ngrambf_v1(4)进行优化的,常量的字符串长度必须要大于等于4才能使用ngrambf_v1(4)进行优化.

这里简单对比一下Set跳数索引和布隆过滤器索引的使用场景,Set跳数索引比较适用于比如Loglevel等低基数并且字段值聚集良好的列,而布隆过滤器比较适合于message日志消息字段,因为当对message字段进行字符串切分成token后,每个gradularities*8192条记录中会产生大量的原子字符串,只有使用布隆过滤器这个跳数索引才能有效的压缩存储,此外我们经常使用这个message字段进行模糊搜索的需求,当然如果基于Loglevel字段+message模糊搜索字段查询就可以既使用Set跳数索引过滤数据,也可以使用布隆过滤器索引过滤数据了.

最后简单的说下使用跳数索引一定要进行测试,我们可以使用trace级别的日志或者explain语法看下服务器的日志确认跳数索引是否真的可以优化查询,并且这个优化的效果要平衡跳数索引自身IO带来的开销要好得多,这样的跳数索引才是有用的跳数索引.

参考文献:
https://clickhouse.com/docs/en/engines/table-engines/mergetree-family/mergetree#functions-support

https://clickhouse.com/docs/en/optimize/skipping-indexes#skip-index-types

你可能感兴趣的:(clickhouse,数据结构,数据库)