clickhouse存储层与计算层
所属分类 clickhouse
浏览量 2991
OLAP特点
读多于写
大宽表,读大量行但是少量列,结果集较小
数据批量写入,且数据不更新或少更新
无需事务,数据一致性要求低
灵活多变,不适合预先建模
预先建模技术虽然可以在特定场景中加速计算,但是无法满足业务灵活多变的发展需求,维护成本过高。
存储层
列式存储引擎
数据有序存储、主键索引、稀疏索引、Sharding、Partitioning、TTL、主备复制等
列存储优点
只读取需要的列 减小IO
同一列,类型相同 ,高效压缩 ,不同的列使用不同的压缩算法
建表时,指定将数据按照某些列进行排序
数据在磁盘上连续存储,且有序摆放。
在进行等值、范围查询时,where条件命中的数据都紧密存储在一个或若干个连续的Block中,减少需要IO的block数量。
连续IO能够充分利用操作系统page cache的预取能力,减少page fault。
主键索引
将每列数据按照index granularity(默认8192行)进行划分,
每个index granularity的开头第一行被称为一个mark行。
主键索引存储该mark行对应的primary key的值。
对于where条件中含有primary key的查询,通过对主键索引进行二分查找,
能够直接定位到对应的index granularity,避免了全表扫描从而加速查询。
主键 可重复 ,去重可使用 ReplacingMergeTree、CollapsingMergeTree、VersionedCollapsingMergeTree
稀疏索引
支持对任意列创建任意数量的稀疏索引
其中被索引的value可以是任意的合法SQL Expression,并不仅仅局限于对column value本身进行索引。
稀疏索引类型
minmax: 以index granularity为单位,存储指定表达式计算后的min、max值;在等值和范围查询中能够帮助快速跳过不满足要求的块,减少IO。
set(max_rows):以index granularity为单位,存储指定表达式的distinct value集合,用于快速判断等值查询是否命中该块,减少IO。
ngrambf_v1(n, size_of_bloom_filter_in_bytes, number_of_hash_functions, random_seed):将string进行ngram分词后,构建bloom filter,能够优化等值、like、in等查询条件。
tokenbf_v1(size_of_bloom_filter_in_bytes, number_of_hash_functions, random_seed): 与ngrambf_v1类似,区别是不使用ngram进行分词,而是通过标点符号进行词语分割。
bloom_filter([false_positive]):对指定列构建bloom filter,用于加速等值、like、in等查询条件的执行。
数据Sharding
sharding策略
random随机分片:写入数据会被随机分发到分布式集群中的某个节点上。
constant固定分片:写入数据会被分发到固定一个节点上。
column value分片:按照某一列的值进行hash分片。
自定义表达式分片:指定任意合法表达式,根据表达式被计算后的值进行hash分片。
在hash sharding的情况下,JOIN计算能够避免数据shuffle,直接在本地进行local join;
支持自定义sharding,可以为不同业务和SQL Pattern定制最适合的分片策略;
利用自定义sharding功能,通过设置合理的sharding expression可以解决分片间数据倾斜问题等。
数据Partitioning
支持PARTITION BY子句 ,建表时可以指定按照任意合法表达式进行数据分区操作
toYYYYMM()将数据按月进行分区、toMonday()将数据按照周几进行分区、对Enum类型的列直接每种取值作为一个分区等。
Partition应用场景
在partition key上进行分区裁剪,只查询必要的数据。灵活的partition expression设置,使得可以根据SQL Pattern进行分区设置,最大化的贴合业务特点。
对partition进行TTL管理,淘汰过期的分区数据。
数据TTL
数据生命周期管理
列级别TTL:当一列中的部分数据过期后,会被替换成默认值;当全列数据都过期后,会删除该列。
行级别TTL:当某一行过期后,会直接删除该行。
分区级别TTL:当分区过期后,会直接删除该分区。
高吞吐写入能力
类LSM Tree 结构,数据写入后定期在后台Compaction。
数据导入时全部是顺序append写,写入后数据段不可更改,在后台compaction时也是多个段merge sort后顺序写回磁盘。
顺序写充分利用了磁盘的吞吐能力,即便在HDD上也有着优异的写入性能。
有限支持delete、update
没有直接支持delete、update操作 , 变相支持
alter table delete where filter_expr
alter table update col=val where filter_expr
删除、更新操作为异步操作,需要后台compation之后才能生效。
主备同步
默认配置下,任何副本都处于active模式,可以对外提供查询服务;
可以任意配置副本个数, 0到多个
不同shard可以配置不同的副本个数,用于解决单个shard的查询热点问题
计算层
单机多核并行 分布式计算 向量化执行与SIMD指令 代码生成 近似计算 复杂数据类型支持
多核并行
将数据划分为多个partition,每个partition再进一步划分为多个index granularity,
然后通过多个CPU核心分别处理其中的一部分来实现并行数据处理。
分布式计算
自动将查询拆解为多个task下发到集群中,然后进行多机并行处理,最后把结果汇聚到一起。
多副本情况,query下发策略
随机下发:在多个replica中随机选择一个;
最近hostname原则:选择与当前下发机器最相近的hostname节点,进行query下发。在特定的网络拓扑下,可以降低网络延时。而且能够确保query下发到固定的replica机器,充分利用系统cache。
in order:按照特定顺序逐个尝试下发,当前一个replica不可用时,顺延到下一个replica。
first or random:在In Order模式下,当第一个replica不可用时,所有workload都会积压到第二个Replica,导致负载不均衡。first or random解决了这个问题:当第一个replica不可用时,随机选择一个其他replica,从而保证其余replica间负载均衡。另外在跨region复制场景下,通过设置第一个replica为本region内的副本,可以显著降低网络延时。
向量化执行与SIMD
数据按列存储,按列计算
向量执行引擎(Vectorized execution engine)
对内存中的列式数据,一个batch调用一次SIMD指令(而非每一行调用一次),
不仅减少了函数调用次数、降低了cache miss,而且可以充分发挥SIMD指令的并行能力,大幅缩短了计算耗时。
SIMD single instruction multiple data,即单指令多数据运算,帮助CPU实现数据并行,提高运算效率。
动态代码生成Runtime Codegen
经典的数据库实现中,通常对表达式计算采用火山模型,将查询转换成operator,比如HashJoin、Scan、IndexScan、Aggregation等。
为了连接不同算子,operator之间采用统一的接口,比如open/next/close。
每个算子内部都实现了父类的这些虚函数,在分析场景中单条SQL要处理数据通常高达数亿行,虚函数的调用开销不再可以忽略不计。
另外,在每个算子内部都要考虑多种变量,比如列类型、列的size、列的个数等,存在着大量的if-else分支判断导致CPU分支预测失效。
Expression级别的runtime codegen,动态地根据当前SQL直接生成代码,然后编译执行。
对于Expression直接生成代码,不仅消除了大量的虚函数调用,而且由于在运行时表达式的参数类型、个数等都是已知的,也消除了不必要的if-else分支判断。
近似计算
以损失一定结果精度为代价,极大地提升查询性能。在海量数据处理中,近似计算价值更加明显。
近似估算distinct values、中位数,分位数等多种聚合函数;
建表DDL支持SAMPLE BY子句,支持对于数据进行抽样处理;
复杂数据类型支持
array、json、tuple、set
上一篇
下一篇
clickhouse表引擎
clickhouse SQL
clickhouse基础
zookeeper集群搭建
互联网广告术语解释
linux sort 命令