当前位置: 首页 > 科技观察

为什么PB级分析型数据库ClickHouse这么快?_0

时间:2023-03-16 19:29:30 科技观察

在交互分析领域,ClickHouse绝对是后起之秀。虽然年轻,但发展空间很大。图片来自Pexels。本文将分享PB级分析型数据库ClickHouse的应用场景、整体架构以及诸多核心特性,帮助理解ClickHouse是如何做到极致性能的存储引擎。希望与您交流。ClickHouse交互分析交互分析简介交互分析,又称OLAP(OnlineAnalyticalProcessing),赋能用户对海量数据进行多维度、交互式的统计分析,从而充分利用数据的价值进行量化运营和辅助决策等,帮助用户提高生产效率。交互分析主要应用于统计报表、即席查询(AdHoc)等领域。前者的查询方式比较固定,后者则是即兴探索分析。代表性场景如:移动互联网中PV、UV、Activity等典型实时报表;互联网内容领域的人群洞察、关联分析等即兴查询。交互分析是数据分析的一种重要方法。与离线分析、流式分析、检索分析一起构成完整的数据分析解决方案。海量数据综合分析需求。与传统关系型数据库以事务处理为主相比,交互式分析解决了PB级数据分析带来的性能和扩展性问题。相比离线分析高达T+1的时效、流式分析相对固定的分析模式、检索分析有限的分析性能,交互式分析的分钟级时效、灵活多维度的分析能力,超-高性能扫描分析性能可以大大提高数据分析的效率,扩大数据分析的应用范围。从数据访问特征来看,交互分析场景有以下典型特征:访问大部分为读请求。写入通常是追加,更新和删除较少。读写不关注事务,强一致性等特性。查询通常访问大量行,但只有部分列是必需的。查询结果通常比访问的原始数据小得多,并且具有可以理解的统计意义。近十年来,放过百花的ClickHouse在交互分析领域蓬勃发展,一大批解决方案爆发式地涌现。目前还没有产品达到类似Oracle/MySQL那样在关系型数据库领域处于绝对领先地位的状态。业界提出的开源或闭源的交互解决方案,主要从大数据和NoSQL两个不同的方向发展而来,旨在为用户提供最佳的交互分析体验。下图展示了不同维度的代表性解决方案,供大家参考:其中,ClickHouse作为PB级交互分析数据库,最初由号称“俄罗斯谷歌”的Yandex公司开发,主要作为全球第一.两大网络流量分析平台Yandex.Metrica(如GoogleAnalytic、友盟统计)的核心存储,实时在线生成网站和移动应用的流量统计报告。自2016年开源以来,ClickHouse以数倍于业界顶级分析数据库的极致性能,成为交互分析领域的后起之秀,并被思科、Splunk、腾讯、阿里等顶级公司采用。以下是ClickHouse等开源OLAP产品的发展趋势统计:性能是衡量OLAP数据库的一个关键指标,我们可以通过ClickHouse官方的测试结果感受到ClickHouse的极致性能,其中绿色代表性能最好,红色代表性能差,红色越深代表性能越弱。从测试结果来看,ClickHouse在几乎所有场景下的性能都是最好的,而且从所有查询的整体来看,ClickHouse领先图灵奖得主MichaelStonebraker创建的Vertica6倍,领先Greenplum18倍。更多测试结果请参考第三方OLAP系统测评。虽然测试使用了非索引表引擎(或表类型),但ClickHouse在单表模式下仍然表现出很强的领先优势。ClickHouse架构集群架构ClickHouse采用典型的基于组的分布式架构。具体的集群架构如上图所示:Shard:集群分为多个分片或组(Shard0...ShardN)。通过Shard的线性扩展能力,支持海量数据的分布式存储和计算。节点:每个分片都包含一定数量的节点(Nodes,即进程),同一个分片中的节点之间互为副本,以保证数据的可靠性。ClickHouse中的副本数可以按需构建,逻辑上不同Shard的副本数可以不同。ZooKeeperService:集群中的所有节点都是平等的,节点之间通过ZooKeeper服务进行分布式协调。数据模型ClickHouse采用经典的表存储模型,属于结构化数据存储系统。我们分别介绍了面向用户的逻辑数据模型和底层面向存储的物理数据模型。①逻辑数据模型从用户的角度来看,ClickHouse的逻辑数据模型有点类似于关系型数据库:一个集群包含多个数据库,一个数据库包含多个表,用于实际存储数据。与传统的关系型数据库不同,ClickHouse是一个分布式系统。如何创建分布式表?ClickHouse的设计是:首先在每个分片的每个节点上创建一个本地表(也就是分片的副本),本地表只在对应的节点中可见;然后创建一个分布式表并映射到之前创建的本地表。这样当用户访问分布式表时,ClickHouse会根据集群架构信息自动将请求转发到对应的本地表。创建分布式表的具体例子如下:#首先创建一个本地表CREATETABLEtable_localONCLUSTERcluster_test(OrderKeyUInt32,#ColumndefinitionOrderDateDate,QuantityUInt8,TotalPriceUInt32,...)ENGINE=MergeTree()#TableenginePARTITIONBYtoYYYYMM(OrderDate)#PartitionmethodORDERBY(OrderDate,OrderKey);#排序方式SETTINGSindex_granularity=8192;#数据块大小#然后,创建分布式表CREATETABLEtable_distributeONCLUSTERcluster_testAStable_localENGINE=Distributed(cluster_test,default,table_local,rand())#关系映射引擎一些关键概念介绍如下,分区,数据块,排序等概念会在物理存储模型部分介绍:继续合并。Distributed:ClickHouse中的关系映射引擎,将分布式表映射到指定集群和数据库下对应的本地表。更直观的,ClickHouse中的逻辑数据模型如下:②物理存储模型接下来介绍一下各个分片副本内部的物理存储模型,如下:数据分区:每个分片副本内部,数据按照PARTITIONBY列进行划分用于分区,分区以目录的形式进行管理。在本文的例子中,表是按时间分区的。列式存储:在每个数据分区内部,使用列式存储。每列涉及两个文件,分别是存放数据的.bin文件和存放偏移量等索引信息的.mrk2文件。数据排序:在每个数据分区中,所有列的数据按照ORDERBY列排序。可以理解为:对于生成这个分区的原始记录行,先按ORDERBY列排序,然后按列拆分存储。数据块:每一列的数据文件实际上是分块存储的,方便数据压缩和查询切分。每个块的记录数不超过index_granularity,默认为8192。主键索引:主键默认与ORDERBY列一致,或者是ORDERBY列的前缀。由于整个分区是按数据块排序存储的,ClickHouse提取每个数据块第一行的主键生成稀疏排序索引,可以在查询时结合过滤条件快速切分数据块。ClickHouse的核心特性为什么ClickHouse有如此高的性能,达到如此迅猛的开发速度?下面我们从ClickHouse的核心特性角度进一步介绍一下。列存储ClickHouse采用列存储,对于分析请求非常高效。一个典型且真实的情况是:如果我们需要分析的数据有50列,每次分析只读取5列,那么通过列存,我们只需要读取必要的列数据即可。与普通行存储相比,可以减少10倍左右的读取、解压、处理的开销,对性能会有质的影响。这是列存数据库在分析场景下相对于行存数据库的一个重要优势。这里有一个来自ClickHouse官方的生动动画,方便大家理解。行存储:从存储系统中读取所有满足条件的行数据,然后在内存中筛选出需要的字段,速度比较慢。列存储:只从存储系统中读取必要的列数据,不读取无用的列,速度非常快。向量化执行在支持列存的基础上,ClickHouse实现了向量化处理的计算引擎,大量的处理操作以向量化的方式执行。与传统火山模型中的逐行处理方式相比,向量化执行引擎采用批处理方式,可以大大减少函数调用开销,减少指令和数据缓存未命中,提高CPU利用效率。并且ClickHouse可以使用SIMD指令进一步加快执行效率。这在一定程度上是ClickHouse优于大量同类OLAP产品的重要因素。以商品订单数据为例,将查询订单总价的过程从传统的按行遍历的过程转换为按块处理的过程。具体如下:编码压缩由于ClickHouse采用列存储,同一列的数据是连续存储的,存储时对底层数据进行排序,所以数据的局部规律性很强,有利于获得一个更高的数据压缩率。此外,除了LZ4、ZSTD等通用压缩算法外,ClickHouse还支持Delta、DoubleDelta、Gorilla等特殊编码算法,进一步提高数据压缩率。其中,DoubleDelta和Gorilla是Facebook专门针对时序数据设计的编码算法。理论上,在列存储环境下,他们可以接近专用时序存储的压缩率。详情请参考大猩猩论文。在实际场景中,ClickHouse通常可以做到10:1的压缩比,大大降低存储成本。同时,超高的压缩比可以降低存储读取开销,提升系统缓存能力,从而提升查询性能。多索引列存用于减少不必要的字段读取,而索引用于减少不必要的记录读取。ClickHouse支持丰富的索引,尽可能减少查询时不必要的记录读取,提高查询性能。ClickHouse中最基本的索引是主键索引。前面我们在物理存储模型中介绍过,ClickHouse的底层数据是按照建表时指定的ORDERBY列排序,根据index_granularity参数划分数据块,然后提取每个数据块的第一行到形成一个稀疏排序索引。用户查询时,如果查询条件包含主键列,可以基于稀疏索引进行快速裁剪。这里用下面的样本数据和对应的主键索引来说明:样本中的主键列是CounterID和Date,这里每7个值作为一个数据块,主键的Marks部分提取并生成索引。当用户查询CounterID等于'h'的数据时,根据索引信息,只需要读取标记号为6和7的两个数据块。ClickHouse支持更多其他索引类型。不同的索引用于不同场景下的查询裁剪。具体总结如下。更详细的介绍可以参考ClickHouse官方文档:物化视图(Cube/Rollup)OLAP分析领域有两个典型的方向:一个是ROLAP,通过列存、索引等各种技术手段提高查询性能.另一种是MOLAP,通过预计算提前生成聚合结果数据,减少查询读取的数据量,是一种计算性能的方法。前者更灵活,但需要相对复杂的技术栈;后者实现起来比较简单,但是要达到极致的性能,需要生成所有常见查询对应的物化视图,消耗大量的计算和存储资源。物化视图的原理如下图所示,可以对不同维度的原始数据进行预计算和汇总:ClickHouse在一定程度上结合了两者,支持一定的MOLAP能力,同时采用ROLAP的方式提升性能如尽可能多。具体实现是MergeTree系列表引擎和MATERIALIZEDVIEW。其实Yandex.Metrica的存储系统也经历过使用纯MOLAP方案的发展过程,具体可以参考ClickHouse的发展历程。用户在使用的时候,可以优先按照ROLAP的思路进行调优,比如主键选择、索引优化、编码压缩等。当你想要更高的性能时,可以考虑结合MOLAP的方式,创建少量的高频查询模式的物化视图,消耗可接受的计算和存储资源,进一步交换查询性能。其他特性除了上面这些,ClickHouse还有很多其他的特性,下面列出。更多细节请参考ClickHouse官方文档:SQL方言:在常见场景下,兼容ANSISQL,支持JDBC、ODBC等丰富接口。权限控制:支持Role-Based权限控制,类似关系型数据库的体验。多机多核并行计算:ClickHouse会充分利用集群中的多节点、多线程进行并行计算,提升性能。近似查询:支持近似查询算法、数据采样等近似查询方案,加快查询性能。ColocatedJoin:在连接数据分散规则一致的多张表时,支持本地化ColocatedJoin,提升查询性能。...ClickHouse的不足上一节介绍了大量ClickHouse的核心特性,让读者了解ClickHouse高性能和快速发展背后的原因。当然,作为后起之秀,ClickHouse远非完美,还有很多方面需要完善。典型代表如下:分布式管控分布式系统通常包括三个重要的组成部分:存储引擎计算引擎分布式管控层ClickHouse有一个非常突出的高性能存储引擎,但是在分布式管理方面比较薄弱和控制层,使得运营和使用成本相对较高。主要体现在:①分布式表ClickHouse对分布式表的抽象不完整。在大多数分布式系统中,用户只感知簇和表,透明地管理分片和副本。在ClickHouse中,用户需要来管理分片和副本。比如在上面描述的建表过程中:用户需要先创建一个本地表(分片的副本),然后再创建一个分布式表,完成分布式表到本地表的映射。②弹性伸缩ClickHouse集群本身可以方便的增加节点,但不支持数据自动均衡。例如,当一个6节点的线上生产集群,由于存储或计算压力大,需要扩容时,我们可以轻松扩容到10个节点。但是,数据不会自动平衡。用户需要对已有的表进行分片或者重建表,然后在整个集群中重新分配写压力。存储压力的平衡取决于历史数据的到期时间。ClickHouse在弹性伸缩方面的缺失,大大增加了业务在进行水平伸缩时的运行压力。基于ClickHouse目前的架构,实现自动均衡是比较复杂的。相关问题的根源在于ClickHouse分组的分布式架构:同一个分片的主从副本绑定到一组节点上。更直接的是,分片之间的数据拆分是按照节点进行的,自动平衡过程不能简单地将分片重新定位到新的节点,这会导致路由信息不正确。但是,这种创建新表并在集群中重新分配全量数据的方式,操作开销过高。③故障恢复类似于弹性伸缩。在节点故障的情况下,ClickHouse不会使用其他机器来填充缺失的副本数据。用户需要先完成节点,然后系统自动同步副本之间的数据。计算引擎虽然ClickHouse在单表性能上表现非常出色,但是在复杂场景下还是有不足之处,缺乏成熟的MPP计算引擎和执行优化器。比如多表关联查询、复杂嵌套子查询等场景查询性能??一般,需要手动优化;缺乏UDF等能力,复杂需求下扩展能力弱。这也与第三方对OLAP系统的评估结果一致。这对于性能如此出色的存储引擎来说是一种遗憾。实时写入ClickHouse采用LSMTree-like架构,建议用户分批写入,每批不少于1000行或每秒不超过一批,以提高集群写入性能。实际测试用例中,在32个vCPU&128G内存的情况下,单节点写入性能可达50MB/s~200MB/s,对应5w~20wTPS。但是ClickHouse不适合实时写。原因是ClickHouse不是典型的LSMTree架构。它不实现内存表结构。每批写入直接作为Tree放在磁盘上(如果单个batch太大,会拆分成MultipleTrees),每条记录实时写入会导致底层有大量小文件层,影响查询性能。这使得ClickHouse不适合需要实时写入的业务。通常需要在业务和ClickHouse之间引入一个数据缓存层来实现批量写入。结束语本文重点分享了ClickHouse的整体架构和诸多核心特性,分析了ClickHouse是如何做到极致性能的存储引擎,从而成为OLAP领域的后起之秀。ClickHouse还很年轻。虽然在某些方面存在不足,但极致性能的存储引擎让ClickHouse成为一个非常好的存储基础。未来,在继续拓展业务的同时,我们将优先布局分布式管控层和计算引擎层,持续优化ClickHouse的易用性和性能,打造业界领先的OLAP分析数据库。同时,我们也会持续输出内核优化、最佳实践等经验,欢迎更多的技术爱好者一起探索交流。参考资料:采用文档:https://clickhouse.tech/docs/zh/introduction/adopters/ClickHouse官方测试结果:https://clickhouse.tech/benchmark/dbms/OLAP系统第三方测评:http://www.clickhouse.com.cn/topic/5c453371389ad55f127768ea专用编码算法支持:https://clickhouse.tech/docs/zh/sql-reference/statements/create/#codecs大猩猩论文:http://www.vldb.org/pvldb/vol8/p1816-teller.pdf索引支持:https://clickhouse.tech/docs/en/engines/table-engines/mergetree-family/mergetree/#table_engine-mergetree-data_skipping-indexesMergeTree系列表引擎:https://clickhouse.tech/docs/en/engines/table-engines/mergetree-family/mergetree/物化视图:https://clickhouse.tech/docs/en/sql-reference/statements/create/view/#物化ClickHouse发展史:https://clickhouse.tech/docs/en/introduction/history/ClickHouse官方文档:https://clickhouse.tech/docs/en/作者:姜国强简介:腾讯实时出海rch研发工程师编辑:陶家龙来源:转载自公众号云家社区(ID:QcloudCommunity)