首页 > 其他分享 >Clickhouse原理解析

Clickhouse原理解析

时间:2024-10-17 20:22:04浏览次数:1  
标签:分区 查询 索引 分片 原理 解析 数据 Clickhouse 分布式

Clickhouse的标签 #OLAP #列式存储

行式数据库和列式数据库适用于不同的业务场景:

  • 如何查询
  • 多久查一次
  • 各类查询的比例
  • 各类查询要求的延迟和吞吐量
  • 每种查询读取多少数据
  • 读和写的关系,比例
  • 数据集的大小
  • 如何使用本地数据集
  • 是否用事务
  • 数据复制和完整性的要求

OLAP

OLAP的特点

对于OLAP的场景,有几个关键特征:

  • 绝大多数请求是读请求
  • 数据以大的批次(>1000)更新,或者根本没有更新
  • 已经入库的数据不能修改
  • 读数据总是提取相当多的行但是列的一小部分
  • 宽表 大量的列
  • 查询少
  • 列的数据相对较小
  • 处理单个查询需要高吞吐量,每台每秒十亿行+
  • 事务不必须
  • 数据一致性要求低
  • 每个查询有一个大表,其他的都很小
  • 查询结果明显小于源数据,适合于单个服务器的RAM中

输入/输出:

  • 分析类查询通常只读取宽表的一小部分列,例如读取100列中的5列,列式数据库可以减少20倍的IO消耗。
  • 数据总是打包成批量,压缩变得容易,数据按照列存储也更容易压缩,降低了IO的体积
  • IO降低,更多数据能被系统缓存

OLAP的架构

OLAP架构分为三类:

  1. R OLAP (Relational OLAP),即直接使用关系模型构建,数据模型通常是星型或雪花模型。这类架构对数据的实时处理能力要求很高。
  2. M OLAP (Multidimensional OLAP), 它是为了缓解ROLAP的性能问题。MOLAP使用多维数据组的形式保存数据,其核心思想是借助预先聚合结构,使用空间换取时间的形式来提升查询性能。这个架构的缺点是,维度预处理可能会导致数据的膨胀。且一般只保留聚合后的结果导致无法查询明细数据。
  3. H OLAP(Hybrid OLAP),即上两者的混合。

以ROLAP为例,传统关系型数据库就被Hive和SparkSQL这类新兴技术取代。但仍然太慢了。MOLAP架构也依托MapReduce或Spark这类新兴技术,作为数据立方体的计算引擎,其预聚合结果的存储载体也转向HBase这类高性能分布式数据库。主流MOLAP架构已经能在亿万级数据的体量下,实现毫秒级查询响应。MOLAP也仍然存在维度爆炸,数据同步实时性不高的问题。

除了ROLAP,MOLAP两类方案以外,也有另辟蹊径的选择,即直接使用搜索引擎实现OLAP查询,如ElasticSearch。在百万级别数据的场景下,ES能支持实时聚合查询,但数据体量增大,性能也捉襟见肘。

另外一条路就是ClickHouse。其具有ROLAP,在线实时查询,完整的DBMS,列式存储,不需要任何数据预处理,批量更新,完善的SQL和函数,支持高可用,不依赖Hadoop复杂生态,开箱即用。

性能对比:https://clickhouse.yandex/benchmark.html

ClickHouse的前世今生

todo

ClickHouse不适用的场景

  • 不支持事务
  • 不擅长根据主键按行粒度查询,不应作为k-v用
  • 不擅长按行删除数据

ClickHouse的核心特性

ClickHouse是一款MPP(Massive Parallel Processing)架构的列式存储数据库。

完备的DBMS功能

  • DDL 动态创建修改删除数据库,表和视图,无需重启
  • DML 动态查询,插入,修改或删除数据
  • 权限控制
  • 数据备份与恢复,提供了数据备份导入导出恢复机制
  • 分布式管理

列式存储与数据压缩

想让查询变得更快,最简单有效的方法就是减少数据扫描范围和数据传输时的大小。按列存与按行存比可以有效地减少扫描数据量:

假设一张数据表A拥有50个字段A1~A50,以及100行数据。现在需要查询前5个字段并进行数据分析,则可以用如下SQL实现:
SELECT A1,A2,A3,A4,A5 FROM A
如果数据按行存储,数据库首先会逐行扫描,并获取每行数据的所有50个字段,再从每一行数据中返回A1~A5这5个字段。不难发现,尽管只需要前面的5个字段,但由于数据是按行进行组织的,实际上还是扫描了所有的字段。如果数据按列存储,就不会发生这样的问题。由于数据按列组织,数据库可以直接获取A1~A5这5列的数据,从而避免了多余的数据扫描。

按列存储的另一个优势是对数据压缩的友好性。压缩的本质是按照一定步长对数据进行匹配扫描,发现重复部分就进行编码转换,如,对abcdefghi和bcdefghi进行压缩,(9,8)表示从下划线往前移动9个字节会匹配8个字节的重复数据。

压缩前:abcdefghi_bcdefghi
压缩后:abcdefghi_(9,8)

压缩的实质就是,数据中的重复项越多,压缩率就越高,数据体量就越小。数据体量越小,则数据在网络中的传输越快,对网络带宽和磁盘IO的压力也就越小。同一列字段重复项的可能性高。Clickhouse数据默认使用LZ4算法压缩,数据总体压缩比可以达到8比1,列式存储除了降低IO和存储压力以外,也为向量化执行做好了铺垫。

向量化执行引擎

向量化执行可以简单看做一项消除程序中循环的优化。为了实现向量化执行,需要利用CPU的SIMD(Single Instruction Multiple Data)指令,它是在CPU寄存器层面实现数据并行操作。ClickHouse目前利用SSE4.2指令集实现向量化执行。

关系模型与SQL查询

关系模型相比文档和键值对等其他模型,拥有更好的描述能力,能够更加清晰地表述实体间的关系。在OLAP领域,已有的大量数据建模工作都是基于关系模型展开的。

多样化的表引擎

多线程与分布式

由于SIMD不适用于带有较多分支判断的场景,ClickHouse也大量使用了多线程技术来提速,与向量化执行形成互补。ClickHouse在数据存取方面,既支持分区(纵向扩展,利用多线程原理),也支持分片(横向扩展,利用分布式原理)。

多主架构

HDFS,Spark,HBase和Elasticsearch这类分布式系统,都采用了Master-Slave主从架构,由一个主节点作为leader统筹全局。而ClickHouse采用Multi-Master多主架构,集群中的每个节点角色对等。多主架构有许多优势,例如对等的角色使系统架构变得更加简单,不用再区分主控节点、数据节点和计算节点,规避了单点故障问题,非常适合与多数据中心,异地多活的场景。

在线查询

即便在复杂查询的场景下,也能够做到极快响应,无需对数据进行任何预处理加工。

数据分片与分布式查询

数据分片是一种分治思想的体现,将数据进行横向切分,ClickHouse支持分片,分片依赖集群,每个集群由1个到多个分片组成,每个分片对应一个服务节点。ClickHouse不像其他分布式系统那样,可以高度自动化分片。它提供了本地表(Local Table)和分布式表(Distributed Table)的概念,一张本地表等于一份数据的分片。分布式表本身不存任何数据,它是本地表的访问代理,作用类似于分库中间件。借助分布式表可以代理访问多个数据分片,实现分布式查询。分布式表读,本地表写。

ClickHouse的架构设计

ClickHouse的核心模块

  • Column & Field
    Column和Field是ClickHouse数据最基础的映射单元,按列存储数据,一列数据由一个Column对象表示。如需操作单列中的一行数据,则需要使用Field对象,Field对象代表一个单值。
  • DataType
    数据的序列化和反序列化工作由DataType负责。
  • Block与Block流
    Block对象可以看做数据表的子集。Block对象本质是由数据对象,数据类型和列名称组成的三元组,即Column, DataType以及列名称字符串。IBlockInputStream和IBlockOutputStream负责数据的读取和关系运算。
  • Table
    底层设计中没有所谓的Table对象,直接使用IStorage接口指代数据表
  • Parser与Interpreter
    Parser分析器分组创建AST对象(Abstract Syntax Tree 抽象语法树),Interpreter负责解释AST,并进一步创建查询的执行管道。他们与IStorage一起,串联整个数据查询的过程。Parser分析器可以将一条SQL语句以递归下降的方法解析成AST语法树的形式。不同SQL语句,会经由不同Parser实现类解析。Interpreter会首先解析AST对象,然后执行业务逻辑(分支判断,设置参数,调用接口等),最终返回IBlock对象,以线程的形式建立一个查询执行管道。
  • Functions与Aggregate Functions
    ClickHouse提供普通函数和聚合函数。普通函数例如四则运算,日期转换,网址提取,IP脱敏等,是没有状态的,采用向量化的方式作用于一整列数据。聚合函数是有状态的,支持序列化和反序列化,能够在分布式节点之间进行传输,以实现增量计算。
  • Cluster & Replication
    ClickHouse的集群由分片(shard)组成,每个分片又通过副本(Replica)组成。与一些流行的分布式系统相区别的是,ClickHouse1个节点只能拥有一个分片,即,如果要实现1分片1副本,至少要部署2个节点。

ClickHouse为什么快

着眼硬件

基于将硬件功效最大化的目的,ClickHouse会在内存中进行Group BY,并使用HashTable装载数据。同时,他们很在意CPU L3级别的缓存,在一个一个细节上做到最优。

特性算法 特殊优化

例如,在字符串搜索方面,针对不同场景,ClickHouse选择了不同算法,对常量,使用Volnitsky算法,对于非常量,使用CPU的向量化执行SIMD,暴力优化;正则匹配使用re2和hyperscan算法。对不同场景也进行不同的针对性优化,例如去重计数uniqueCombined函数,会根据数据量不同选择不同算法,数据较少时,选择array保存;数据量中等时,选择hashset;数据量很大时,使用HyperLogLog算法。

最佳实践

分区表

数据分区是针对本地数据而言的纵向切分,借助数据分区,查询过程中跳过不必要的目录提升查询性能。

分布式DDL执行

将普通DDL语句转换成分布式执行,只需要加上ON CLUSTER cluster_name即可。集群中的每个节点都会以相同的顺序执行相同的语句。

数据删除与修改

DELETE和UPDATE这类操作被称为Mutation查询,Mutation语句是一种“很重”的操作,更适用于批量数据修改和删除,不支持事务,一旦被提交执行,会立刻对现有数据产生影响,无法回滚,并且它是一个异步后台过程,语句被提交后就会立即返回,执行的具体进度要通过System.mutations系统表查询。

删除的过程:
每执行一次DELETE语句,都会在mutations系统表生成一条对应的执行计划,当is_done字段为1时表示执行完成。同时,在数据表的根目录下,会以mutation_id为名生成与之对应的日志文件用于记录相关信息。数据删除的过程是以数据表的每个分区目录为单位,将所有目录重写为新的目录,新目录命名规则是在原有名称上加上system.mutations.block_numbers.number。数据在重写过程中会将需要删除的数据去掉。旧目录不会被立刻删除,而是标记为非激活状态,等MergeTree引擎下一次合并动作触发时,才会被物理删除。

数据字典

数据字典是ClickHouse提供的一种简单实用的存储媒介,以键值和属性映射的形式定义数据。字典中的数据会主动或者被动加载到内存,支持动态更新。由于字典数据常驻内存的特性,适合保存常量或经常使用的维度表数据,避免不必要的JOIN查询。

表引擎

合并树表引擎家族

MergeTree

MergeTree在写入一批数据时,数据总会以数据片段的形式写入磁盘,且数据片段不可修改。为了避免片段过多,ClickHouse会通过后台线程定期合并这些数据片段,属于相同分区的数据片段会被合成一个新的片段。

创建MergeTree数据表

PARTITION BY

选填,分区键,指定数据以何种标准进行分区,可以是单个列字段,可以是多个列字段,也支持列表达式。若不声明分区键,则ClickHouse会生成一个名为all的分区。

ORDER BY

必填,排序键,指定一个数据片段内,数据以何种标准排序。默认情况下主键(PRIMARY KEY)与排序键相同,可以为单列或多列字段。

PRIMARY KEY

选填,主键,声明后会根据主键字段生成一级索引加速表查询,默认情况下,主键与排序键相同,所以直接通过使用ORDER BY为指定主键。与其他数据库不同的是MergeTree主键允许重复数据(ReplacingMergeTree可以去重)

SAMPLE BY

选填,抽样表达式,声明数据以何种标准进行采样。如果有使用,需要在主键配置中声明同样表达式,抽样表达式需要配合SAMPLE子查询使用。

SETTINGS

index_granularity选填,这是一个非常重要的参数,表示索引的粒度,默认值是8192,即默认情况,每间隔8192行数据才生成一条索引。

MergeTree存储结构

磁盘上物理存储结构
目录结构

  • partition 分区目录,相同分区数据最终会合并到一个目录,不同分区数据不会合并在一起。
  • checksums.txt 校验文件,二进制存储。保存了各个文件的size和size的hash,校验文件的完整和正确性
  • columns.txt列信息文件,明文存储
    columns
  • count.txt 计数文件,当前分区数据总行数,明文存储
    count
  • primary.idx 一级索引,二进制存储,存放稀疏索引
  • [column].bin 数据文件,默认LZ4压缩格式存储
  • [column].mrk 列字段标记文件,二进制存储,保存了.bin文件数据的偏移量信息。标记文件与稀疏索引对齐,又和.bin文件一一对应,所以标记文件建立了primary.idx稀疏索引和.bin数据文件之间的映射关系。先通过primary.idx找到数据的偏移量信息.mrk,再通过偏移量直接从.bin文件读取数据
  • [column].mrk2 如果使用了自适应大小的索引间隔,则标记文件以.mrk2命名。工作原理和作用与.mrk标记文件相同。
  • partition.dat与minmax_[column].idx,如果使用了分区键,则额外生成partition.dat和minmax索引文件,二进制存储。partition.dat保存当前分区下分区表达式最终生成的值,minmax索引记录当前分区下分区字段对应原始数据的最大最小值。
  • skp_idx_[column].idx 与skp_idx_[column].mrk,如果建表时声明了二级索引,则会额外生成相应的二级索引与标记文件。二级索引又叫做跳数索引,目前拥有minmax,set,ngrambf_v1,tokenbf_v1四种类型。

数据分区的规则

MergeTree数据分区的规则由分区ID决定,

  • 不指定分区键,分区ID默认为all,所有数据写入这个目录
  • 使用整型,直接按照该整型的字符串形式输出作为分区ID的取值
  • 使用日期类型,按照YYYYMM等格式字符串作为分区ID
  • 使用其他类型,不属于整型和日期,则通过128位Hash算法取其Hash值作为分区ID
  • 若分区键是多个列,则通过每个的列对应的分区ID用中短线依次拼接

分区规则

分区目录

分区目录并不只是分区ID,而是后面有一串数字:
分区目录
测试

1_1表示最小数据块编号和最大数据块编号,_0表示目前合并的层级即被合并过的次数。
合并过程中:

  • MinBlockNum,取同一分区内所有目录中最小的MinBlockNum值
  • MaxBlockNum,取同一分区内所有目录中最大的MaxBlockNum值
  • Level取同一分区内最大的Level值并加1

分区合并的过程

一级索引

主键定义后根据index_granularity间隔为数据表生成一级索引保存到primary.idx文件,索引数据按照primary key排序。一级索引采取稀疏索引实现,由于稀疏索引占用空间小,所以索引数据常驻内存。
稀疏索引与稠密索引

索引数据生成规则:

索引生成规则
索引生成规则-2

索引查询过程

有一份测试数据共192条记录,主键为string类型,从A000到A191, MergeTree的索引粒度index_granularity=3,根据索引生成规则,primary.idx的物理存储如下:
p.idx

根据索引数据,MergeTree会将此数据片段划分成192/3=64个MarkRange,相邻步长为1,如下图:
markRange

索引查询步骤:

  1. 生成查询条件区间。如where ID = 'A003'-> ['A003', 'A003'], ID > 'A000' -> ('A000', +inf)
  2. 递归交集判断
  3. 合并MarkRange区间
    如下图,判断的步长为8,由merge_tree_coarse_index_granularity指定
    索引查询过程

二级索引

MergeTree支持二级索引,跳数索引。建表时需要声明跳数索引,索引声明后会额外生成相应的索引与标记文件(skp_idx_[column].idx与skp_idx_[column].mrk)。对跳数索引而言,index_granularity定义了数据的粒度,granularity定义了聚合信息汇总的粒度即granularity定义了一行跳数索引能够跳过多少个index_granularity区间的数据。如下图的minmax跳数索引:
minmax跳数索引

MergeTree目前支持4种跳数索引,分别是minmax,set,ngrambf_v1,tokenbf_v1:

  • minmax 记录一段数据内的最小和最大值
  • set set索引直接记录字段的取值,完整形式是set(max_rows),表示在一个index_granularity内,索引最多记录的行数,如果max_rows=0,则表示无限制。
  • ngrambf_v1 数据短语的布隆表过滤器,只支持String和FixedString类型。ngrambf_v1只能提升in,notIn,like,equals和notEquals查询性能,完整表达式为ngrambf_v1(n,size_of_bloom_filter_in_bytes,number_of_hash_functions,random_seed),n为根据n的长度将数据切割为token短语,其他是布隆过滤器参数
  • tokenbf_v1是ngrambf_v1的变种,同样也是一种布隆过滤器索引,只是token的处理方法不一样

数据存储

首先数据是经过压缩,默认LZ4算法,其次,数据会事先按照ORDER BY的声明排序,最后,数据是以压缩数据块的形式被组织并写入.bin文件中的。

压缩数据块

一个压缩数据块由头信息和压缩数据两部分组成。头信息有9位字节,1个UInt8和2个UInt32,分别代表使用的压缩算法类型,压缩后数据大小和压缩前数据大小。每个压缩数据块的体积按照其压缩前的数据字节大小,被严格控制在64KB-1MB,上下限分别由min_compress_block_size默认65536和max_compress_block_size默认1048576参数指定。写入过程遵循,如果单批次数据<64KB,则继续获取下一批数据,直到>=64KB,生成下一个压缩数据块。单批次位于64KB-1MB,直接生成压缩数据块,单批次>1MB,截断1MB大小,剩下数据继续按此规则执行。
压缩数据块

压缩和解压的动作本身有性能损耗,所以需要控制被压缩数据的大小,以求在性能损耗和压缩率之间的平衡。读取某列数据时,需要将压缩数据加载到内存并解压,通过压缩数据块,可以在不读取整个.bin文件的情况下将读取粒度降低到压缩数据块级别。

数据标记

数据标记(.mrk)是衔接一级索引(primary.idx)和数据(.bin)的桥梁,数据标记和索引区间是对齐的,也和.bin文件一一对应。一行标记数据包含两个整型数值的偏移量信息。分别表示在此段数据区间内在对应的.bin压缩文件中,压缩数据块的起始偏移量,和压缩块解压后其未压缩数据的起始偏移量。标记数据与一级索引不同,并不常驻内存,而是使用LRU缓存策略加快其取用速度。

数据标记

完整的写入过程:
写入过程

查询过程:
查询过程

如果一条查询语句没有指定任何WHERE条件,或是指定了WHERE条件,但条件没有匹配到任何索引,就不能预先减少数据范围。在后续查询的时候会扫描所有分区目录和目录内索引段的最大区间。虽然不能减少数据范围,但是MergeTree仍然能借助数据标记,多线程的形式同时读取多个压缩数据块,以提升性能。

MergeTree系列表引擎

ReplacingMergeTree

MergeTree虽然有主键,但它的主键却没有唯一键的约束。ReplacingMergeTree就是这种背景下为了数据去重而设计的,它能在合并分区时删除重复数据。ORDER BY是去除重复数据的依据而非PRIMARY KEY。但是ReplacingMergeTree是以分区为单位删除重复数据的,只有在相同的数据分区内重复的数据才可以被删除,不同数据分区之间的重复数据依然不能被剔除,且只有在合并分区的时候才会触发删除重复数据的逻辑。

SummingMergeTree

对于不需要明细数据,只关注查询数据的归总结果的场景。它能在合并分区时,按照预先定义的条件根据ORDER BY的定义聚合汇总数据,将同一分组下的多行数据汇总合并成一行,既减少了数据行,又降低了后续汇总查询的开销。

一般情况下ORDER BY和PRIMARY KEY取值相同,不必单独声明PRIMARY KEY。如果需要同时定义ORDER BY 和PRIMARY KEY,通常只有一种可能,就是明确希望这两者不同,这种情况通常在使用SummingMergeTree或AggregatingMergeTree时才会出现。因为SummingMergeTree和AggregatingMergeTree的聚合都是根据ORDER BY进行的,主键与聚合条件定义分离,为聚合条件留下空间。

如果同时声明了ORDER BY与PRIMARY KEY,MergeTree会强制要求PRIMARY KEY列字段必须是ORDER BY的前缀。这种约束保证了即时两者定义不同的情况下,主键是排序键的前缀,不会出现索引与数据顺序混乱的问题。同理,该汇总逻辑也只会在合并分区的时候触发,同一分区数据会汇总,不同分区不会汇总。汇总字段会使用SUM计算,非汇总字段会根据ORDER BY取第一行的数据。

AggregatingMergeTree

AggregatingMergeTree可以看做SummingMergeTree的升级版,很多设计思路是一致的,例如同时定义ORDER BY和PRIMARY KEY的原因和目的。AggregatingMergeTree有会根据ORDER BY声明的字段聚合,具体聚合的方式由建表时的聚合语句决定,如下。

CREATE TABLE agg_table(
id String,
city String,
code AggregateFunction(uniq,String),
value AggregateFunction(sum,UInt32),
create_time DateTime
)ENGINE = AggregatingMergeTree()
PARTITION BY toYYYYMM(create_time)
ORDER BY (id,city)
PRIMARY KEY id

除了建表语句之外,在后续的读写方式都有改变,例如写入时,需要调用与聚合方法对应的State函数,uniq->uniqState;查询时,需要调用与聚合方法对应的Merge函数,uniq-> uniqMerge

INSERT INTO TABLE agg_table
SELECT 'A000','wuhan',
uniqState('code1'),
sumState(toUInt32(100)),
'2019-08-10 17:00:00'
SELECT id,city,uniqMerge(code),sumMerge(value) FROM agg_table
GROUP BY id,city

但上述方法并不是该引擎最常见的使用方式,该引擎最常见的方式和结合物化视图使用,作为物化视图的表引擎。如下,新增数据针对底表,查询数据使用物化视图

CREATE TABLE agg_table_basic(
id String,
city String,
code String,
value UInt32
)ENGINE = MergeTree()
PARTITION BY city
ORDER BY (id,city)
CREATE MATERIALIZED VIEW agg_view
ENGINE = AggregatingMergeTree()
PARTITION BY city
ORDER BY (id,city)
AS SELECT
id,
city,
uniqState(code) AS code,
sumState(value) AS value
FROM agg_table_basic
GROUP BY id, city

CollapsingMergeTree

CollapsingMergeTree通过以增代删的思路,支持行级数据修改和删除的表引擎。它通过定义一个sign标记位字段,记录数据行的状态,如果sign为1,则是一条有效数据,如果sign为-1,则该数据需要删除。分区合并时,同一数据分区内,sign为1和-1的会被抵消删除。

ReplicatedMergeTree

ReplicatedMergeTree示意图
ReplicatedMergeTree借助ZooKeeper的消息日志广播功能,实现副本实例之间的数据同步功能。
组合关系

数据查询

在绝大部分场景都该避免使用SELECT * 形式查数据,因为通配符对于采用列式存储的数据库而言没有任何好处。

在使用JOIN查询时,首先应该遵循左大右小的原则,即把数据量小的表放在右侧,因为执行JOIN查询时,右表都会被全部加载到内存中与左表比较。JOIN查询目前没有缓存支持,大量维度属性补全的查询场景中,建议使用字典代替JOIN查询。

副本与分片

副本

ReplicatedMergeTree的设计特点:

  • 依赖ZooKeeper,执行INSERT和ALTER查询的时候,需要借助zk的分布式协同能力,实现多个副本之间的同步。
  • 表级别的副本
  • 多主架构,任意一个副本上执行INSERT ALTER效果相同。
  • Block数据块 在INSERT写入数据时,会根据max_insert_block_size将数据切分成若干Block数据块。Block数据块是数据写入的基本单元。具有写入的原子性和唯一性。

副本协同的过程1
副本协同的过程2

分片

副本虽然能降低数据丢失风险,提升查询性能(读写分离),但数据表容量的问题让然没有解决,单表的性能瓶颈只能靠分片来突破。ClickHouse的数据分片需要结合Distributed表引擎一同使用。Distributed表引擎自身不存储任何数据,作为分布式表的一层透明代理,在集群内部自动开展数据的写入,分发,查询,路由等工作。

  • 本地表,通常以_local为后缀进行命名。本地表是承接数据的载体,可以使用非Distributed的任意表引擎。一张本地表对应了一个数据分片。
  • 分布式表,通常以_all为后缀进行命名。分布式表只能使用Distributed引擎,它与本地表形成一对多的映射关系,日后将通过分布式表代理操作多张本地表。
    ENGINE = Distributed(cluster, database, table, [,sharding_key])
    其中,sharding_key是分片键,选填参数。在数据写入的过程中,分布式表会依据分片键的规则,将数据分布到各个host节点的本地表。
    创建分布式表
CREATE TABLE test_shard_2_all ON CLUSTER sharding_simple (
id UInt64
)ENGINE = Distributed(sharding_simple, default, test_shard_2_local,rand())

然后再创建本地表

CREATE TABLE test_shard_2_local ON CLUSTER sharding_simple (
id UInt64
)ENGINE = MergeTree()
ORDER BY id
PARTITION BY id

Distributed表的操作分为如下几类:

  • 会作用于本地表的查询,对于INSERT和SELECT,Distributed将会以分布式的方式作用于local本地表。
  • 只会影响Distributed自身,不会作用于本地表的查询,例如CREATE,DROP,ALTER等,例如要彻底删除一张分布式表,需要分别删除分布式表和本地表。
  • 不支持的查询;Distributed表不支持任何MUTATION类型的操作,包括ALTER DELETE和ALTER UPDATE

分片键

分片键要求返回一个整型取值,例如分片键可以是一个具体的整型字段,也可以是返回整型的表达式如rand()

分布式写入的核心流程

向集群分片写入数据时,通常有两种思路,一种是借助外部计算系统,事先将数据均匀分布,再由计算系统直接写入各个本地表。第二种思路是通过Distributed表引擎代理写入分片数据

流程图

副本复制数据的流程

数据在多个副本之间,有两种复制实现方式:一种是借助Distributed表引擎,由它将数据写入副本;另一种是借助ReplicatedMergeTree表引擎实现副本数据的分发。
分发副本数据

多分片查询的核心流程

Distributed表会拆分成若干个针对本地表的子查询,然后向各个分片发起查询,最终通过UNION汇总结果。

Global优化分布式子查询

如果分布式查询中使用子查询如IN,IN查询的子句是本地表,所以要改成GLOBAL IN。

标签:分区,查询,索引,分片,原理,解析,数据,Clickhouse,分布式
From: https://www.cnblogs.com/rachel-aoao/p/18451375/clickhouse

相关文章

  • NDT的原理分析与实现
    文章目录前言一、基本原理1.原理介绍2.优化流程(1)初始化阶段(2)配准阶段前言相关中文博客1:CSDN强烈推荐相关中文博客2:CSDN3D变换雅可比海森矩阵计算:CSDN一、基本原理1.原理介绍在使用NDT(NormalDistributionsTransform)进行扫描配准时,目标是找到当前扫描......
  • Bilidown v1.2.4 B站在线视频下载解析工具中文单文件版
    Bilidown是一款专为B站视频下载而设计的工具,一款简洁好用的B站视频下载工具,支持由UP主上传的单集,多集以及相关封面,弹幕,字幕,音乐,刮削等等,支持任意粒度批量组合,登录后最高支持到1080P,大会员可获取所有画质及音质。Bilidown具有强大的功能和简便的操作界面。Bilidown可以下载B站上......
  • OCR文字识别:深入剖析原理与技术实现全流程
    在当今信息化时代,OCR(OpticalCharacterRecognition,光学字符识别)技术已经成为我们日常生活和工作中不可或缺的一部分。无论是证件识别、名片识别,还是车牌识别,OCR技术都发挥着重要作用。本文将深入剖析OCR文字识别的原理与技术实现全流程,帮助读者更好地理解这一技术。一、OCR技......
  • PostgreSQL慢SQL收集和解析
    postgresql通过log_statement参数记录慢SQL语句PostgreSQL可以不借助任何扩展实现对SQL日志的记录,主要依赖于两个参数,也即log_statement和log_min_duration_statement,1,记录的sql类型log_statement='all'可以是none,ddl,mod,all2,记录的sql执行时间阈值log_min_duration_stat......
  • 《帝国时代4》游戏启动时崩溃提示“缺少ole32.dll”文件的原因解析及解决教程
    当玩家们满心欢喜地准备进入《帝国时代4》那精彩的游戏世界时,却突然遭遇游戏启动时崩溃,并提示“缺少ole32.dll”文件,这无疑令人感到十分扫兴和困惑。究竟是什么原因导致了这一情况的发生?又该如何去解决呢?下面将为大家详细解析原因并给出解决教程。崩溃提示“缺少ole32.dll”......
  • 《光环:无限》游戏启动时黑屏崩溃弹窗“找不到acge24.dll”文件的原因解析及解决方法
    当玩家们满心期待地启动《光环:无限》这款精彩的游戏时,却突然遭遇黑屏崩溃,并且弹窗提示“找不到acge24.dll”文件,这无疑给玩家们的热情浇上了一盆冷水。究竟是什么原因导致了这一情况的发生?又该如何解决呢?下面将为大家详细解析并给出相应的解决方法。崩溃弹窗“找不到acge24.d......
  • Disk Group基础概念与深度解析
    DiskGroup基础概念与深度解析 ......
  • VM Storage Policies深度解析
    VMStoragePolicies深度解析  ......
  • 【2024华为OD-E卷-100分-内存资源分配】(题目+思路+Java&C++&Python解析+在线测试)
    在线评测链接题目描述有一个简易内存池,内存按照大小粒度分类,每个粒度有若干个可用内存资源,用户会进行一系列内存申请,需要按需分配内存池中的资源返回申请结果成功失败列表。分配规则如下:分配的内存要大于等于内存的申请量,存在满足需求的内存就必须分配,优先分配粒度小的......
  • 图像cv常用操作原理和方法说明
    图像cv常用操作原理和方法说明灰度、平滑、滤波、仿射变化、形态学BORDERTYPE边填充边扩展时填充值的方式cv.BORDER_DEFAULT等同于BORDER_REFLECT_101可通过cv.copyMakeBorder查看效果灰度变化作用如果拍照时曝光不足或曝光过度,照片会灰蒙蒙的或者过白,这实......