IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> ClickHouse -> 正文阅读

[大数据]ClickHouse

ClickHouse
????简介
????????实时数据分析数据库,开发语言为C++,是一个用于联机分析的列式数据库管理系统,简称CK,工作速度比传统方法快100-1000倍。每秒钟每台机器每秒处理数十亿多行和数千兆字节的数据
????????特点
????????????开源的列存储数据库管理系统,支持线性扩展,简单方便,高可靠性
????????????容错跑分快:比Vertica快5倍,比Hive快279倍,比MySQL快800倍,其可处理的数据级别已经达到10亿级别
????????????功能多:支持数据统计分析各种场景,支持类SQL查询,异地复制部署
????????优点
????????????真正的面向列的DBMS(ClickHouse是一个DBMS,而不是一个单一的数据库。它允许在运行时创建表和数据库、加载数据和运行查询,而无需重新配置和重新启动服务器)
????????????数据压缩(一些面向列的DBMS(INFINIDB CE 和 MonetDB)不使用数据压缩。但是,数据压缩确实是提高了性能)
????????????磁盘存储的数据(许多面向列的DBMS(SPAHANA和GooglePowerDrill))只能在内存中工作。但即使在数千台服务器上,内存也太小了。)
????????????多核并行处理(多核多节点并行化大型查询)
????????????在多个服务器上分布式处理(在clickhouse中,数据可以驻留在不同的分片上。每个分片都可以用于容错的一组副本,查询会在所有分片上并行处理)
????????????SQL支持(ClickHouse sql 跟真正的sql有不一样的函数名称。不过语法基本跟SQL语法兼容,支持JOIN/FROM/IN 和JOIN子句及标量子查询支持子查询)
????????????向量化引擎(数据不仅按列式存储,而且由矢量-列的部分进行处理,这使得开发者能够实现高CPU性能)
????????????实时数据更新(ClickHouse支持主键表。为了快速执行对主键范围的查询,数据使用合并树
(MergeTree)进行递增排序。由于这个原因,数据可以不断地添加到表中)
????????????支持近似计算(统计全国到底有多少人?143456754 14.3E)
????????????数据复制和对数据完整性的支持(ClickHouse使用异步多主复制。写入任何可用的复本后,数据将
分发到所有剩余的副本。系统在不同的副本上保持相同的数据。数据在失败后自动恢复)
????????缺点
????????????没有完整的事务支持,不支持Transaction想快就别Transaction
????????????缺少完整Update/Delete操作,缺少高频率、低延迟的修改或删除已存在数据的能力,仅用于批量删除或修改数据。
????????????聚合结果必须小于一台机器的内存大小
????????????支持有限操作系统,正在慢慢完善
????????????不适合Key-value存储,不支持Blob等文档型数据库
????系统架构
????????ClickHouse 是一个真正的列式数据库管理系统(DBMS)。在 ClickHouse 中,数据始终是按列存储的,包括矢量(向量或列块)执行的过程。
????????????
????????Column与Field
????????????Column和Field是ClickHouse数据最基础的映射单元。内存中的一列数据由一个Column对象表示。
Column对象分为接口和实现两个部分,在IColumn接口对象中,定义了对数据进行各种关系运算
的方法。几乎所有的操作都是不可变的:这些操作不会更改原始列,但是会创建一个新的修改后的列。
在大多数场合,ClickHouse都会以整列的方式操作数据,但凡事也有例外。如果需要操作单个具体
的数值 ( 也就是单列中的一行数据 ),则需要使用Field对象,Field对象代表一个单值。
与Column对象的泛化设计思路不同,Field对象使用了聚合的设计模式。在Field对象内部聚合了
Null、UInt64、String和Array等13种数据类型及相应的处理辑。
????????数据类型DataType
????????????IDataType 负责序列化和反序列化:读写二进制或文本形式的列或单个值构成的块。 IDataType直接与表的数据类型相对应。
IDataType 与??IColumn 之间的关联并不大。不同的数据类型在内存中能够用相同的??IColumn 实现来表示。
IDataType 仅存储元数据。
数据的序列化和反序列化工作由DataType负责。IDataType接口定义了许多正反序列化的方法,它
们成对出现。IDataType也使用了泛化的设计模式,具体方法的实现逻辑由对应数据类型的实例承载。
DataType虽然负责序列化相关工作,但它并不直接负责数据的读取,而是转由从Column或Field对象获取。
????????块Block
????????????Block 是表示内存中表的子集(chunk)的容器,是由三元组: (IColumn, IDataType, 列名)构成的集合。
ClickHouse内部的数据操作是面向Block对象进行的,并且采用了流的形式。Block对象可以看作数据表的子集。
Block并没有直接聚合Column和DataType对象,而是通过ColumnWithTypeAndName对象进行间接引用。
????????块流BlockStreams
????????????块流用于处理数据。我们可以使用块流从某个地方读取数据,执行数据转换,或将数据写到某个地方。
Block流操作有两组顶层接口:
IBlockInputStream负责数据的读取和关系运算, IBlockInputStream 具有??read 方法,其能够在数据可用时获取下一个块。
IBlockOutputStream负责将数据输出到下一环节。 IBlockOutputStream 具有??write 方法,其能够将块写到某处。
IBlockInputStream接口总共有60多个实现类,这些实现类大致可以分为三类:
第一类用于处理数据定义的DDL操作
第二类用于处理关系运算的相关操作
第三类则是与表引擎呼应,每一种表引擎都拥有与之对应的BlockInputStream实现
IBlockOutputStream的设计与IBlockInputStream如出一辙。这些实现类基本用于表引擎的相关处
理,负责将数据写入下一环节或者最终目的地。
????????Formats格式
????????????数据格式同块流一起实现。用于向客户端输出数据的?展示?格式
如块流 IBlockOutputStream 提供的??Pretty 格式,也有其它输入输出格式,比如
TabSeparated 或??JSONEachRow 。
如行流: IRowInputStream 和??IRowOutputStream 。它们允许你按行 pull/push 数据,而不是按块。
????????数据读写I/O
????????????对于面向字节的输入输出,有??ReadBuffer 和??WriteBuffer 这两个抽象类。
ReadBuffer 和??WriteBuffer 由一个连续的缓冲区和指向缓冲区中某个位置的一个指针组成。
ReadBuffer 和??WriteBuffer 的实现用于处理文件、文件描述符和网络套接字(socket),也用于实现压缩和其它用途。
????????数据表Table
????????????在数据表的底层设计中并没有所谓的Table对象
表由??IStorage 接口表示。该接口的不同实现对应不同的表引擎。
表引擎是ClickHouse的一个显著特性,不同的表引擎由不同的子类实现。
IStorage 中最重要的方法是??read 和??write ,除此之外还有??alter 、 rename 和??drop 等方法。
表的??read 方法能够返回多个??IBlockInputStream 对象以允许并行处理数据。多个块输入流能
够从一个表中并行读取。
AST 查询被传递给??read 方法,表引擎可以使用它来判断是否能够使用索引,从而从表中读取更少的数据。
????????解析器Parser
????????????查询由一个手写递归下降解析器解析。比如,??ParserSelectQuery 只是针对查询的不同部分递归
地调用下层解析器。
解析器创建??AST 。 AST 由节点表示,节点是??IAST 的实例。
???????? 解释器Interpreter
????????????解释器负责从??AST 创建查询执行流水线。
简单的解释器,如??InterpreterExistsQuery 和??InterpreterDropQuery
复杂的解释器,如??InterpreterSelectQuery 。
查询执行流水线由块输入或输出流组成。
SELECT 查询的解释结果是从??FROM 字句的结果集中读取数据的??IBlockInputStream ;
INSERT 查询的结果是写入需要插入的数据的??IBlockOutputStream ;
Parser分析器可以将一条SQL语句以递归下降的方法解析成AST语法树的形式。不同的SQL语句,会经由不同的Parser实现类解析。
????????函数Functions
????????????ClickHouse主要提供两类函数—普通函数(Functions)和聚合函数(Aggregate Functions)。
????????普通函数Functions
????????????普通函数不会改变行数 - 它们的执行看起来就像是独立地处理每一行数据。
实际上,函数不会作用于一个单独的行上,而是作用在以??Block 为单位的数据上,以实现向量查询执行。
普通函数由IFunction接口定义,拥有数十种函数实现,采用向量化的方式直接作用于一整列数据。
????????聚合函数Aggregate Functions
????????????聚合函数是状态函数。它们将传入的值激活到某个状态,并允许你从该状态获取结果。
聚合函数由IAggregateFunction接口定义,相比无状态的普通函数,聚合函数是有状态的。
以COUNT聚合函数为例,其AggregateFunctionCount的状态使用整型UInt64记录。
聚合状态可以被序列化和反序列化,以在分布式查询执行期间通过网络传递或者在内存不够的时候将其写到硬盘。
????????Cluster与Replication
????????????ClickHouse的集群由分片 ( Shard ) 组成,而每个分片又通过副本 ( Replica ) 组成。
这种分层的概念,在一些流行的分布式系统中十分普遍。
ClickHouse的1个节点只能拥有1个分片,也就是说如果要实现1分片、1副本,则至少需要部署2个服务节点。
分片只是一个逻辑概念,其物理承载还是由副本承担的。
????MergeTree
????????简介
????????????表引擎是ClickHouse设计实现中的一大特色
ClickHouse拥有非常庞大的表引擎体系,其共拥有合并树、外部存储、内存、文件、接口和其他6大类20多种表引擎。
合并树家族自身也拥有多种表引擎的变种。其中MergeTree作为家族中最基础的表引擎,提供了主键索引、数据分区、数据副本和数据采样等基本能力,而家族中其他的表引擎则在MergeTree的基
础之上各有所长。
????????创建与存储
????????????MergeTree在写入一批数据时,数据总会以数据片段的形式写入磁盘,且数据片段不可修改。
为了避免片段过多,ClickHouse会通过后台线程,定期合并这些数据片段,属于相同分区的数据片段会被合成一个新的片段。
这种数据片段往复合并的特点,也正是合并树名称的由来。
????????????配置选项
????????????????PARTITION BY [选填]:分区键,用于指定表数据以何种标准进行分区。
分区键既可以是单个列字段,也可以通过元组的形式使用多个列字段,同时它也支持使用列表达式。
如果不声明分区键,则ClickHouse会生成一个名为all的分区。
合理使用数据分区,可以有效减少查询时数据文件的扫描范围。
????????????????ORDER BY [必填]:排序键,用于指定在一个数据片段内,数据以何种标准排序。
默认情况下主键(PRIMARY KEY)与排序键相同。
排序键既可以是单个列字段,例如ORDER BY CounterID,也可以通过元组的形式使用
多个列字段,例如ORDERBY(CounterID,EventDate)。
当使用多个列字段排序时,以ORDERBY(CounterID,EventDate)为例,在单个数据片
段内,数据首先会以CounterID排序,相同CounterID的数据再按EventDate排序。
????????????????PRIMARY KEY [选填]:主键,顾名思义,声明后会依照主键字段生成一级索引,用于加速表查询。
默认情况下,主键与排序键(ORDER BY)相同,所以通常直接使用ORDER BY代为指定主键,无须刻意通过PRIMARY KEY声明。
所以在一般情况下,在单个数据片段内,数据与一级索引以相同的规则升序排列。
与其他数据库不同,MergeTree主键允许存在重复数据(ReplacingMergeTree可以去重)。
????????????????SAMPLE BY [选填]:抽样表达式,用于声明数据以何种标准进行采样。
如果使用了此配置项,那么在主键的配置中也需要声明同样的表达式。抽样表达式需要配合SAMPLE子查询使用,这项功能对于选取抽样数据十分有用
????????????????SETTINGS:
index_granularity [选填]:
index_granularity对于MergeTree而言是一项非常重要的参数,它表示索引的粒度,默认值为8192。
MergeTree的索引在默认情况下,每间隔8192行数据才生成一条索引
index_granularity_bytes [选填]
在19.11版本之前,ClickHouse只支持固定大小的索引间隔,由index_granularity控制,默认为8192。
在新版本中,它增加了自适应间隔大小的特性,即根据每一批次写入数据的体量大小,动态划分间隔大小。而数据的体量大小,正是由index_granularity_bytes参数控制的,默认为10M(10×1024×1024),设置为0表示不启动自适应功能。
enable_mixed_granularity_parts [选填]
设置是否开启自适应索引间隔的功能,默认开启。
merge_with_ttl_timeout [选填]
从19.6版本开始,MergeTree提供了数据TTL的功能
storage_policy [选填]:
从19.15版本开始,MergeTree提供了多路径的存储策略
????????存储格式
????????????MergeTree表引擎中的数据是拥有物理存储的,数据会按照分区目录的形式保存到磁盘之上
????????????????
????????????一张数据表的完整物理结构分为3个层级,依次是数据表目录、分区目录及各分区下具体的数据文
partition:分区目录,余下各类数据文件(primary.idx、[Column].mrk、[Column].bin等)
都是以分区目录的形式被组织存放的,属于相同分区的数据,最终会被合并到同一个分区目
录,而不同分区的数据,永远不会被合并在一起。
checksums.txt:校验文件,使用二进制格式存储。它保存了余下各类文件(primary.idx、
count.txt等)的size大小及size的哈希值,用于快速校验文件的完整性和正确性。
columns.txt:列信息文件,使用明文格式存储。用于保存此数据分区下的列字段信息
count.txt:计数文件,使用明文格式存储。用于记录当前数据分区目录下数据的总行数,
primary.idx:一级索引文件,使用二进制格式存储。用于存放稀疏索引,一张MergeTree表
只能声明一次一级索引(通过ORDERBY或者PRIMARY KEY)。借助稀疏索引,在数据查询的
时能够排除主键条件范围之外的数据文件,从而有效减少数据扫描范围,加速查询速度。
[Column].bin:数据文件,使用压缩格式存储,默认为LZ4压缩格式,用于存储某一列的数
据。由于MergeTree采用列式存储,所以每一个列字段都拥有独立的.bin数据文件,并以列字
段名称命名(例如CounterID.bin、EventDate.bin等)。
[Column].mrk:列字段标记文件,使用二进制格式存储。标记文件中保存了.bin文件中数据
的偏移量信息。标记文件与稀疏索引对齐,又与.bin文件一一对应,所以MergeTree通过标记
文件建立了primary.idx稀疏索引与.bin数据文件之间的映射关系。即首先通过稀疏索引
(primary.idx)找到对应数据的偏移量信息(.mrk),再通过偏移量直接从.bin文件中读取
数据。由于.mrk标记文件与.bin文件一一对应,所以MergeTree中的每个列字段都会拥有与其
对应的.mrk标记文件(例如CounterID.mrk、EventDate.mrk等)。
[Column].mrk2:如果使用了自适应大小的索引间隔,则标记文件会以.mrk2命名。它的工作
原理和作用与.mrk标记文件相同。
partition.dat与minmax_[Column].idx:如果使用了分区键,例如PARTITION BY
EventTime,则会额外生成partition.dat与minmax索引文件,它们均使用二进制格式存储。
partition.dat用于保存当前分区下分区表达式最终生成的值;而minmax索引用于记录当前分
区下分区字段对应原始数据的最小和最大值。
skp_idx[Column].idx与skp_idx[Column].mrk:如果在建表语句中声明了二级索引,则会额外
生成相应的二级索引与标记文件,它们同样也使用二进制存储。二级索引在ClickHouse中又
称跳数索引,目前拥有minmax、set、ngrambf_v1和tokenbf_v1四种类型。这些索引的最终
目标与一级稀疏索引相同,都是为了进一步减少所需扫描的数据范围,以加速整个查询过程。
????????数据分区
????????????数据分区规则
????????????????MergeTree数据分区的规则由分区ID决定,而具体到每个数据分区所对应的ID,则是由分区键的取值决定的。
????????????????分区键支持使用任何一个或一组字段表达式声明,其业务语义可以是年、月、日或者组织单位等任何一种规则。
????????????????针对取值数据类型的不同,分区ID的生成逻辑目前拥有四种规则:
不指定分区键:
如果不使用分区键,即不使用PARTITION BY声明任何分区表达式,则分区ID默认取名为all,所有的数据都会被写入这个all分区。
使用整型:
如果分区键取值属于整型(兼容UInt64,包括有符号整型和无符号整型),且无法转换为日期类型YYYYMMDD格式
则直接按照该整型的字符形式输出,作为分区ID的取值。
使用日期类型:
如果分区键取值属于日期类型,或者是能够转换为YYYYMMDD格式的整型
则使用按照YYYYMMDD进行格式化后的字符形式输出,并作为分区ID的取值。
使用其他类型:
如果分区键取值既不属于整型,也不属于日期类型
例如String、Float等,则通过128位Hash算法取其Hash值作为分区ID的取值。
????????????分区目录命名
????????????????一个完整分区目录的命名公式
????????????????????201905表示分区目录的ID;
1_1分别表示最小的数据块编号与最大的数据块编号;
而最后的_0则表示目前合并的层级。
????????????????????????
????????????????PartitionID_MinBlockNum_MaxBlockNum_Level
????????????????????PartitionID:分区ID
MinBlockNum和MaxBlockNum:顾名思义,最小数据块编号与最大数据块编号。
Level:合并的层级,可以理解为某个分区被合并过的次数,或者这个分区的年龄。数值越高表示年龄越大。
????????????分区目录合并
????????????????MergeTree的分区目录和传统意义上其他数据库有所不同。
????????????????首先,MergeTree的分区目录并不是在数据表被创建之后就存在的,而是在数据写入过程中被创建的。
也就是说如果一张数据表没有任何数据,那么也不会有任何分区目录存在。
????????????????其次,它的分区目录在建立之后也并不是一成不变的。
????????????????????在其他某些数据库的设计中,追加数据后目录自身不会发生变化,只是在相同分区目录中追加
新的数据文件。
而MergeTree完全不同,伴随着每一批数据的写入(一次INSERT语句),MergeTree都会生
成一批新的分区目录。
即便不同批次写入的数据属于相同分区,也会生成不同的分区目录。
也就是说,对于同一个分区而言,也会存在多个分区目录的情况。
在之后的某个时刻(写入后的10~15分钟,也可以手动执行optimize查询语句)
ClickHouse会通过后台任务再将属于相同分区的多个目录合并成一个新的目录。
已经存在的旧分区目录并不会立即被删除,而是在之后的某个时刻通过后台任务被删除(默认
8分钟)。
????????????????新目录名称的合并方式遵循规则:
????????????????????MinBlockNum:取同一分区内所有目录中最小的MinBlockNum值。
MaxBlockNum:取同一分区内所有目录中最大的MaxBlockNum值。
Level:取同一分区内最大Level值并加1。
????????一级格式
????????????MergeTree的主键使用PRIMARY KEY定义,待主键定义之后,MergeTree会依据
index_granularity间隔(默认8192行),为数据表生成一级索引并保存至primary.idx文件内,索引数据按照PRIMARYKEY排序。
???????????? 稀疏索引
????????????????primary.idx文件内的一级索引采用稀疏索引实现。
稠密索引中每一行索引标记都会对应到一行具体的数据记录。
稀疏索引中每一行索引标记对应的是一段数据,而不是一行。
????????????????????
????????????????稀疏索引的优势是显而易见的,它仅需使用少量的索引标记就能够记录大量数据的区间位置信息,且数据量越大优势越为明显。
以默认的索引粒度(8192)为例,MergeTree只需要12208行索引标记就能为1亿行数据记录提供索引。
由于稀疏索引占用空间小,所以primary.idx内的索引数据常驻内存,取用速度自然极快。
????????????????索引文件查看命令:od -An -i -w4 primary.idx
????????????索引粒度
????????????????索引粒度就如同标尺一般,会丈量整个数据的长度,并依照刻度对数据进行标注,最终将数据标记成多个间隔的小段
????????????????????
????????????索引规则
????????????????由于是稀疏索引,所以MergeTree需要间隔index_granularity行数据才会生成一条索引记录,其索引值会依据声明的主键字段获取。
????????????????单主键
????????????????????第0(81920)行CounterID取值57,第8192(81921)行CounterID取值1635,而第16384(8192*2)行CounterID取值3266
最终索引数据将会是5716353266。
????????????????????????
????????????????多主键
????????????????????
????????????????索引查询过程
????????????????????MarkRange
MarkRange在ClickHouse中是用于定义标记区间的对象。
MergeTree按照index_granularity的间隔粒度,将一段完整的数据划分成了多个小的间隔数据段,一个具体的数据段即是一个MarkRange。
MarkRange与索引编号对应,使用start和end两个属性表示其区间范围。
通过与start及end对应的索引编号的取值,即能够得到它所对应的数值区间。而数值区间表示了此MarkRange包含的数据范围。
????????????????????案例分析
????????????????????????主键ID为String类型,ID的取值从A000开始,后面依次为A001、A002……直至A189为止。
MergeTree的索引粒度index_granularity=3
MergeTree会将此数据片段划分成189/3=63个小的MarkRange
???????????????????????? ????
????????????????????索引查询其实就是两个数值区间的交集判断。
????????????????????????一个区间是由基于主键的查询条件转换而来的条件区间;
????????????????????????一个区间是刚才所讲述的与MarkRange对应的数值区间。
????????????????????查询步骤
????????????????????????
????????????????????????生成查询条件区间:首先,将查询条件转换为条件区间。
????????????????????????????WHERE ID = 'A003'
['A003', 'A003']
WHERE ID > 'A000'
('A000', +inf)
WHERE ID < 'A188'
(-inf, 'A188')
WHERE ID LIKE 'A006%'
['A006', 'A007')
????????????????????????递归交集判断:以递归的形式,依次对MarkRange的数值区间与条件区间做交集判断。从最大的区间[A000,+inf)开始:
????????????????????????????如果不存在交集,则直接通过剪枝算法优化此整段MarkRange。
如果存在交集,且MarkRange步长大于8(end-start),则将此区间进一步拆分成8个子区间,并重复此规则,继续做递归交集判断。
如果存在交集,且MarkRange不可再分解(步长小于8),则记录MarkRange并返回。
????????????????????????合并MarkRange区间:将最终匹配的MarkRange聚在一起,合并它们的范围。
????????二级索引
????????????二级索引又称跳数索引,由数据的聚合信息构建而成。
根据索引类型的不同,其聚合信息的内容也不同。跳数索引的目的与一级索引一样,也是帮助查询时减少数据扫描的范围。
跳数索引在默认情况下是关闭的,需要设置allow_experimental_data_skipping_indices
SET allow_experimental_data_skipping_indices = 1
跳数索引需要在CREATE语句内定义,它支持使用元组和表达式的形式声明,其完整的定义语法
INDEX index_name expr TYPE index_type(...) GRANULARITY granularity
????????????粒度
????????????????granularity定义了一行跳数索引能够跳过多少个index_granularity区间的数据。
????????????????????首先,按照index_granularity粒度间隔将数据划分成n段,总共有[0,n-1]个区间(n=total_rows/index_granularity,向上取整)
接着,根据索引定义时声明的表达式,从0区间开始,依次按index_granularity粒度从数据中
获取聚合信息,每次向前移动1步,聚合信息逐步累加。
最后,当移动granularity次区间时,则汇总并生成一行跳数索引数据。
??????????????????????? ?
????????????分类
????????????????MergeTree共支持4种跳数索引,分别是minmax、set、ngrambf_v1和tokenbf_v1。一张数据表支持同时声明多个跳数索引。
????????????????????CREATE TABLE skip_test (
ID String,
URL String,
Code String,
EventTime Date,
INDEX a ID TYPE minmax GRANULARITY 5,
INDEX b(length(ID) * 8) TYPE set(2) GRANULARITY 5,
INDEX c(ID,Code) TYPE ngrambf_v1(3, 256, 2, 0) GRANULARITY 5,
INDEX d ID TYPE tokenbf_v1(256, 2, 0) GRANULARITY 5
) ENGINE = MergeTree()
????????????????minmax:
????????????????????minmax索引记录了一段数据内的最小和最大极值,其索引的作用类似分区目录的minmax索引,能够快速跳过无用的数据区间
????????????????set
????????????????????set索引直接记录了声明字段或表达式的取值(唯一值,无重复),其完整形式为
set(max_rows),其中max_rows是一个阈
值,表示在一个index_granularity内,索引最多记录的数据行数。
????????????????ngrambf_v1:
????????????????????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:token长度,依据n的长度将数据切割为token短语。
size_of_bloom_filter_in_bytes:布隆过滤器的大小。
number_of_hash_functions:布隆过滤器中使用Hash函数的个数。
random_seed:Hash函数的随机种子。
????????????????tokenbf_v1:
????????????????????tokenbf_v1索引是ngrambf_v1的变种,同样也是一种布隆过滤器索引。
tokenbf_v1除了短语token的处理方法外,其他与ngrambf_v1是完全一样的。
tokenbf_v1会自动按照非字符的、数字的字符串分割token
????????数据存储
????????????列式存储
????????????????在MergeTree中,数据按列存储。而具体到每个列字段,数据也是独立存储的,每个列字段都拥有
一个与之对应的.bin数据文件。也正是这些.bin文件,最终承载着数据的物理存储。
????????????????数据文件以分区目录的形式被组织存放,所以在.bin文件中只会保存当前分区片段内的这一部分数据
????????????????优势:
????????????????????一是可以更好地进行数据压缩
????????????????????二是能够最小化数据扫描的范围
????????????????存储方式
????????????????????首先,数据是经过压缩的,目前支持LZ4、ZSTD、Multiple和Delta几种算法,默认使用LZ4算法;
????????????????????其次,数据会事先依照ORDER BY的声明排序;
????????????????????最后,数据是以压缩数据块的形式被组织并写入.bin文件中的
???????????? 数据压缩
????????????????一个压缩数据块由头信息和压缩数据两部分组成。
????????????????????头信息固定使用9位字节表示,具体由1个UInt8(1字节)整型和2个UInt32(4字节)整型组
分别代表使用的压缩算法类型、压缩后的数据大小和压缩前的数据大小
bin压缩文件是由多个压缩数据块组成的,而每个压缩数据块的头信息则是基于
CompressionMethod_CompressedSize_UncompressedSize公式生成的每个压缩数据块的体积,按照其压缩前的数据字节大小,都被严格控制在64KB~1MB
其上下限分别由min_compress_block_size(默认65536)与max_compress_block_size(默
认1048576)参数指定。
而一个压缩数据块最终的大小,则和一个间隔(index_granularity)内数据的实际大小相关
????????????????????????
????????????????数据写入过程
????????????????????MergeTree在数据具体的写入过程中,会依照索引粒度(默认情况下,每次取8192行),按批次获取数据并进行处理
单个批次数据size<64KB :如果单个批次数据小于64KB,则继续获取下一批数据,直至累积到size>=64KB时,生成下一个压缩数据块。
单个批次数据64KB<=size<=1MB :如果单个批次数据大小恰好在64KB与1MB之间,则直接生成下一个压缩数据块。
单个批次数据size>1MB :如果单个批次数据直接超过1MB,则首先按照1MB大小截断并生成
下一个压缩数据块。剩余数据继续依照上述规则执行。
????????????????????????
????????????????优势
????????????????????其一,虽然数据被压缩后能够有效减少数据大小,降低存储空间并加速数据传输效率,但数据的压缩和解压动作,其本身也会带来额外的性能损耗。所以需要控制被压缩数据的大小,以求在性能损耗和压缩率之间寻求一种平衡。
????????????????????其二,在具体读取某一列数据时(.bin文件),首先需要将压缩数据加载到内存并解压,这样
才能进行后续的数据处理。通过压缩数据块,可以在不读取整个.bin文件的情况下将读取粒度
降低到压缩数据块级别,从而进一步缩小数据读取的范围。
????????????????????????
  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2021-12-01 17:46:35  更:2021-12-01 17:48:59 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 9:03:17-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码