新网的网站建设一般是多少钱,科技有限公司简介模板,公司发布网站需要备案吗,app研发录大数据之ClickHouse
简介
ClickHouse是一种列式数据库管理系统#xff0c;专门用于高性能数据分析和数据仓库应用。它是一个开源的数据库系统#xff0c;最初由俄罗斯搜索引擎公司Yandex开发#xff0c;用于满足大规模数据分析和报告的需求。
特点
开源的列式存储数据库…大数据之ClickHouse
简介
ClickHouse是一种列式数据库管理系统专门用于高性能数据分析和数据仓库应用。它是一个开源的数据库系统最初由俄罗斯搜索引擎公司Yandex开发用于满足大规模数据分析和报告的需求。
特点
开源的列式存储数据库管理系统支持线性扩展简单方便高可靠性容错跑分快可处理的数据级别达到10亿级别功能多支持数据统计分析各种场景支持类SQL查询异地复制部署
优点
真正的面向列的DBMS不是一个单一的数据库它允许在运行时创建表和数据库、加载数据和运行查询而无需重新配置和重新启动服务器使用数据压缩提高了性能磁盘存储数据多核并行处理多核多节点并行化大型查询在多个服务器上分布式处理数据可以驻留在不同的分片上每个分片都可以用于容错的一组副本查询会在所有分片上进行处理SQL支持基本语法跟SQL语法兼容向量化引擎数据不仅按列式存储而且由矢量-列的部分进行处理这使得开发者能够实现高CPU性能实时数据更新为了快速执行对主键范围的查询数据使用合并数MergeTree进行递增排序支持近似计算数据复制和对数据完整性的支持使用异步多主复制写入任何可用的副本后数据将分发到所有剩余的副本。系统在不同的副本上保持相同的数据数据在失败后自动恢复
缺点
没有完整的事务支持不支持Transaction缺少完整Update/Delete操作缺少高频率、低延迟的修改或删除已存在数据的能力仅用于批量删除或修改数据聚合结果必须小于一台机器的内存大小支持有限操作系统不适合Key-value存储不支持Blob等文档型数据库
系统架构
ClickHouse是一个真正的列式数据库管理系统。在ClickHouse中数据始终是按列存储的包括矢量执行的过程。
Column与Field
Column和Field是ClickHouse数据最基础的映射单元。内存中的一列数据由一个Column对象表示。Column对象分为接口和实现两部分在IColumn接口对象中定义了对数据进行各种关系运算的方法。ClickHouse是以整列的方式操作数据如果需要操作单个具体的数值也就是单列中的一行数据时则需要使用Field对象Field对象代表一个单值。Column对象使用的是泛化设计思路Field对象使用的是聚合的设计思路。
数据类型DataType
IDataType负责序列化和反序列化读写二进制或文本形式的列或单个值构成的块。直接与表的数据类型相对应IDataType与IColumn之间的关联并不大。不同的数据类型在内存中能够用相同的IColumn实现来表示。IDataType仅存储元数据。数据的序列化和反序列化工作由DataType负责。IDataType接口定义了许多正反序列化的方法它们成对出现。IDataType使用的是泛化的设计模式具体方法的实现逻辑由对应数据类型的实例承载。DataType虽然负责序列化相关工作但它并不直接负责数据的读取而是转由从Column或Field对象获取。
块Block
Block是表示内存中表的子集的容器是由IColumn、IDataType、列名构成的集合ClickHouse内部的数据操作是面向Block对象进行的并且采用了流的形式。
块流BlockStreams 块流用来处理数据它可以从某个地方读取数据执行数据转换或将数据写到某个地方 Block流操作的两组顶层接口 IBlockInputStream负责数据的读取和关系运算 IBlockInputStream 具有 read 方法其能够在数据可用时获取下一个块。IBlockOutputStream负责将数据输出到下一环节。 IBlockOutputStream 具有 write 方法其能够将块写到某处。 IBlockInputStream接口的实现类大致可以分为三类 第一类用于处理数据定义的DDL操作第二类用于处理关系运算的相关操作第三类则是与表引擎呼应每一种表引擎都拥有与之对应的BlockInputStream实现
Formats格式
数据格式同块流一起实现。用于向客户端输出数据的展示格式
数据读写I/O
有ReadBuffer和WriteBuffer两个抽象类来面向字节输入输出它们是由一个连续的缓冲区和指向缓冲区中某个位置的一个指针组成它们用于处理文件、文件描述符和网络套接字也用于实现压缩等。
数据表Table
表由IStorage接口表示。该接口的不同实现对应不同的表引擎。表引擎是ClickHouse的一个显著特性不同的表引擎由不同的子类实现。表的read方法能够返回多个IBlockInputStream对象以允许并行处理数据。多个块输入流能够从一个表中并行读取。AST查询被传递给read方法表引擎可以使用它来判断是否能够使用索引从而从表中读取更少的数据。
解析器Parser
查询由一个手写递归下降解析器解析。解析器创建AST。
解释器Interpreter
解释器负责从AST创建查询执行流水线。查询执行流水线由块输入或输出流组成。Parser分析器可以将一条SQL语句以递归下降的方法解析成AST语法树的形式。不同的SQL语句会经由不同的Parser实现类解析。
函数Functions ClickHouse主要提供两类函数 普通函数Functions 不会改变行数它们的执行看起来就像是独立地处理每一行数据。实际上函数不会作用于一个单独的行上而是作用在以Block为单位的数据上以实现向量查询执行。普通函数采用向量化的方式直接作用于一整列数据。 聚合函数Aggregate Functions 聚合函数是状态函数它们将传入的值激活到某个状态并允许你从该状态获取结果。聚合状态可以被序列化和反序列化以在分布式查询执行期间通过网络传递或者在内存不够的时候将其写到硬盘。
Cluster与Replication
ClickHouse的集群由分片Shard组成而每个分片又通过副本Replica组成。ClickHouse的1个节点只能拥有1个分片也就是说如果要实现1分片、1副本则至少需要部署2个服务节点。分片只是一个逻辑概念其物理承载还是由副本承担的。
MergeTree
ClickHouse拥有非常庞大的表引擎体系其共拥有合并树、外部存储、内存、文件、接口和其他6大类20多种表引擎。合并树家族自身也拥有多种表引擎的变种。其中MergeTree作为家族中最基础的表引擎提供了主键索引、数据分区、数据副本和数据采样等基本能力而家族中其他的表引擎则在MergeTree的基础之上各有所长。
创建与存储
MergeTree在写入一批数据时数据总会以数据片段的形式写入磁盘且数据片段不可修改。为了避免片段过多ClickHouse会通过后台线程定期合并这些数据片段属于相同分区的数据片段会被合并成一个新的片段。这种数据片段往复合并的特点也正式合并树名称的由来。MergeTree表引擎中的数据是拥有物理存储的数据会按照分区目录的形式保存到磁盘之上
数据分区
数据分区规则 MergeTree数据分区的规则由分区ID决定而具体到每个数据分区所对应的ID则是由分区键的取值决定的。 分区键支持使用任何一个或一组字段表达式声明。 分区ID的生成逻辑有四种规则 不指定分区键如果不适用分区键则分区ID默认取名为all所有的数据都会被写入这个all分区。使用整型如果分区键取值属于整型且无法转换为日期类型YYYYMMDD格式则直接按照该整型的字符形式输出作为分区ID的取值。使用日期类型如果分区键取值属于日期类型或者是能够转换为YYYYMMDD格式的整型则使用按照YYYYMMDD进行格式化后的字符形式输出并作为分区ID的取值。使用其他类型如果分区键取值既不属于整型也不属于日期类型则通过128位Hash算法取其Hash值作为分区ID的取值。
分区目录命名 一个完整分区目录的命名公式 201905表示分区目录的ID1_1分别表示最小的数据块编号与最大的数据块编号而最后的_0则表示目前合并的层级PartitionID分区IDMinBlockNum和MaxBlockNum最小数据块编号与最大数据块编号Level合并的层级可以理解为某个分区被合并过的次数或者这个分区的年龄。数值越高表示年龄越大
分区目录合并 首先MergeTree的分区目录并不是在数据表被创建之后就存在的而是在数据写入过程中被创建的也就是说如果一张数据表没有任何数据那么也不会有任何分区目录存在。 其次它的分区目录在建立之后也并不是一成不变的。 在其他某些数据库的设计中追加数据后目录自身不会发生变化只是在相同分区目录中追加新的数据文件。而MergeTree完全不同伴随着每一批数据的写入MergeTree都会生成一批新的分区目录。即便不同批次写入的数据属于相同分区也会生成不同的分区目录。之后ClickHouse会通过后台任务再将属于相同分区的多个目录合并成一个新的目录。已经存在的旧分区目录并不会立即被删除而是在之后的某个时刻通过后台任务被删除默认8分钟。
一级索引
稠密索引中每一行索引标记都会对应到一行具体的数据记录。稀疏索引中每一行索引标记对应的是一段数据而不是一行。稀疏索引的优势在于它仅需使用少量的索引标记就能够记录大量数据的区间位置信息且数据量越大优势越明显。
索引查询过程 MarkRange在ClickHouse中是用于定义标记区间的对象。 MergeTree按照index_granularity的间隔粒度将一段完整的数据划分成了多个小的间隔数据段一个具体的数据段即是一个MarkRange。 MarkRange与索引编号对应使用start和end两个属性表示其区间范围。 通过与start及end对应的索引编号的取值即能够得到它所对应的数值区间。而数值区间表示了此MarkRange包含的数据范围。 查询步骤 生成查询条件区间首先将查询条件转换为条件区间。 递归交集判断以递归的形式一次对MarkRange的数值区间与条件区间做交集判断。 如果不存在交集则直接通过剪枝算法优化此整段MarkRange。如果存在交集且MarkRange步长大于8(end-start)则将此区间进一步拆分成8个子区间并重复此规则继续做递归交集判断。如果存在交集且MarkRange不可再分解步长小于8则记录MarkRange并返回。 合并MarkRange区间将最终匹配的MarkRange聚在一起合并它们的范围。
二级索引
二级索引又称跳数索引由数据的聚合信息构建而成。根据索引类型的不同其聚合信息的内容也不同。跳数索引的目的与一级索引一样也是帮助查询时减少数据扫描的范围。
粒度
首先按照index_granularity粒度间隔将数据划分成n段总共有[0n-1]个区间接着根据索引定义时声明的表达式从0区间开始一次按index_granularity粒度从数据中获取聚合信息每次向前移动1步聚合信息逐步累加。最后当移动granularity次区间时则汇总并生成一行跳数索引数据。
分类
minmax记录了一段数据内的最小和最大极值其索引的作用是能够快速跳过无用的数据区间。set直接记录了声明字段或表达式的取值其完整形式为set(max_rows)其中max_rows是一个阈值表示在一个index_granularity内索引最多记录的数据行数。ngrambf_v1记录的是数据短语的布隆表过滤器只支持String和FixedString数据类型。tokenbf_v1是ngrambf_v1的升级版同样也是一种布隆过滤器索引会自动按照非字符的、数字的字符串分割token。
数据存储
列式存储 在MergeTree数据按列存储。而具体到每个列字段数据也是独立存储的每个列字段都拥有一个与之对应的.bin数据文件。这些.bin文件也是最终承载着数据的物理存储。 数据文件以分区目录的形式被组织存放所以在.bin文件中只会保存当前分区片段内的这一部分数据。 优势 可以更好地进行数据压缩能够最小化数据扫描的范围 存储方式 首先数据是经过压缩的默认使用LZ4算法其次数据会事先依照ORDER BY的声明排序最后数据是以压缩数据块的形式被组织并写入.bin文件中的
数据压缩 一个压缩数据块由头信息和压缩数据两部分组成。 头信息固定使用9位字节表示具体由1个UInt81字节整型和2个UInt324字节整型组成分别代表使用的压缩算法类型、压缩后的数据大小和压缩前的数据大小每个压缩数据块的体积按照其压缩前的数据字节大小都被严格控制在64KB1MB一个压缩数据块最终的大小和一个间隔index_granularity内数据的实际大小相关 数据写入过程 MergeTree在数据具体的写入过程中会依照索引粒度默认情况下每次取8192行按批次获取数据并进行处理单个批次数据size64KB 如果单个批次数据小于64KB则继续获取下一批数据直至累积到size64KB时生成下一个压缩数据块单个批次数据64KBsize1MB 如果单个批次数据大小恰好在64KB与1MB之间则直接生成下一个压缩数据块单个批次数据size1MB 如果单个批次数据直接超过1MB则首先按照1MB大小截断并生成下一个压缩数据块。剩余数据继续依照上述规则执行 优势 其一虽然数据被压缩后能够有效减少数据大小降低存储空间并加速数据传输效率但数据的压缩和解压动作其本身也会带来额外的性能损耗。所以需要控制被压缩数据的大小以求在性能损耗和压缩率之间寻求一种平衡。其二在具体读取某一列数据时.bin文件首先需要将压缩数据加载到内存并解压这样才能进行后续的数据处理。通过压缩数据块可以在不读取整个.bin文件的情况下将读取粒度降低到压缩数据块级别从而进一步缩小数据读取的范围。
数据读写流程
写入数据
数据写入的第一步是生成分区目录伴随着每一批数据的写入都会生成一个新的分区目录。在后续的某一时刻属于相同分区的目录会依照规则合并到一起接着按照index_granularity索引粒度会分别生成primary.idx一级索引、每一个列字段的.mrk数据标记和.bin压缩数据文件。
查询数据
数据查询的本质可以看作一个不断减小数据范围的过程。在最理想的情况下MergeTree首先可以依次借助分区索引、一级索引和二级索引将数据扫描范围缩至最小。然后再借助数据标记将需要解压与计算的数据范围缩至最小。