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

为什么ClickHouse的查询速度快?

时间:2023-03-13 04:21:58 科技观察

1。从存储引擎的角度来看,ClickHouse速度快的秘诀在于利用存储引擎的特殊设计,充分降低磁盘I/O对查询速度的影响。从用户提交SQL语句查询到最终输出结果的过程中,大量的时间消耗在磁盘I/O上。在很多情况下,I/O占用的时间可以达到整个时间的90%以上。存储引擎磁盘I/O的优化可以获得非常大的收益。ClickHouse的存储引擎设计中大量优化的目的也是为了减少磁盘I/O。本节将从这个角度解读ClickHouse存储引擎的优化。1、预排序ClickHouse与传统事务型数据库的区别之一是ClickHouse写入数据文件的数据是有序的。这就是本节要介绍的预排序:在将数据写入磁盘之前对数据进行排序,保证数据在磁盘上是有序的。预排序是数据库系统中广泛使用的技术。在实现范围搜索时,可以将大量的随机读转化为顺序读,从而有效提高I/O效率,减少范围查询时的I/O时间。预排序实现与点查找的未排序数据相同的性能。因此,预排序可以在不降低点查找性能的情况下有效地提高范围查询的性能。2、列存数据库和行存数据库最根本的区别在于,列存数据库是将一行数据拆分成多个数据文件。在列存储数据库中,同一列的所有数据都在同一个文件中,因此在硬盘上是连续的。该特性特别适用于OLAP的低范式查询场景。3.压缩ClickHouse中减少I/O的另一种方法是压缩。压缩可以减少读取和写入的数据量,从而减少I/O时间。不能在所有场景中引入压缩。很明显,压缩必然会导致压缩和解压的CPU消耗。这是一种用CPU时间换取I/O时间的方法。由于事务型数据库在大多数情况下是对行进行操作的,如果对每一行进行一次压缩和解压,那么所消耗的时间会远远大于磁盘I/O时间。这就是事务数据库不使用压缩技术的原因。但ClickHouse不同。ClickHouse的最小处理单元是块。一个块一般由8192行数据组成。ClickHouse一次压缩针对8192行数据,大大减少了CPU的压缩和解压时间。同时,ClickHouse是一个列式存储的数据库,同一列中的数据相对比较有规律,所以可以带来比较大的压缩比。因此,分块+压缩成为ClickHouse中非常关键的优化方式。2.不同于从计算引擎的角度设计存储引擎,ClickHouse计算引擎的设计在很多方面都存在很大的争议。一方面,矢量化引擎的精妙设计令人叹为观止,另一方面,相对粗糙的SQL分析和优化器(解释器)也让ClickHouse在执行某些动作时让用户咬牙切齿。一、ClickHouse速度快的前提在正式进入本节内容之前,我们首先需要明确一个前提:ClickHouse并不能在所有场景下都实现强大的性能。因此,有必要分析ClickHouse满足的前提条件,以获得最强的查询性能。ClickHouse计算引擎最精妙的设计在于向量化引擎,所以计算引擎带来的ClickHouse的速度一定是向量化引擎的加持。ClickHouse的计算引擎慢是因为没有成本优化器,计算引擎慢也是因为没有成本优化器。基于这两个逻辑,我们可以分析出ClickHouse速度快的前提。1)大量使用向量化运算ClickHouse提供了很多内置函数,在使用这些内置函数时,ClickHouse会自动进行向量化优化。因此,尽量使用提供的内置函数进行计算,而不是自己编写SQL语句。下面展示错误的SQL写法和正确的写法。SELECT(2/(1.0+exp(-2*x))-1)astanh_x......//错误的写法SELECTtanh(x)astanh_x......//正确的写法写的,直接使用ClickHouse的内置函数2)查询语句中不使用Join子句,或者尽量少用Join操作。ClickHouse没有成本优化器,导致Join操作时ClickHouse内存不足,导致查询失败。事实上,Join的性能问题不仅仅是ClickHouse遇到的。任何数据库在遇到大表的join时,都可能导致查询时间突然增加。大数据中的Spark计算引擎对Join操作做了很多优化,并以其强大的CBO实现了Join算法的自动选择。在此基础上,AQE(AdaptiveQueryExecution,自适应查询引擎)解决了大表join操作中数据倾斜的性能问题。正是因为ClickHouse没有实现CBO,所以ClickHouse在实现Join操作的时候选择很少。特别是在分布式大表的Join操作中,ClickHouse只实现了BroadcastJoin算法,大大降低了ClickHouse的Join能力。在使用ClickHouse时,应尽可能避免连接操作。Join操作在ODS建模过程中大量存在。因此,ClickHouse在设计良好的DW上运行矢量化查询的性能最高。读者应尽量避免使用ClickHouse进行ODS建模工作。当数据量很大时,这种建模工作应该尽可能的下推到Spark去执行。2.ClickHouse的快速性当满足上述两个条件时,ClickHouse应该能够在不考虑存储引擎影响的情况下,在计算引擎上发挥最大的性能。ClickHouse计算引擎的本质是利用CPU提供的硬件加速特性。另外,ClickHouse客观上确实在一些环节上存在一些问题。我个人认为这些问题与ClickHouse的定位有关。ClickHouse在设计之初就明确了自己的定位——充分发挥单机性能的OLAP引擎。在此基础上,分布式加入能力其实并不重要。毕竟业界已经有了Spark。完全可以在Spark之上构建ClickHouse。Spark可以解决建模问题,ClickHouse强大的DW分析能力可以实现最终的OLAP一英里问题。作为用户,我们应该清醒地认识ClickHouse速度快的前提,自觉避开ClickHouse的雷区,不要把ClickHouse用于它不擅长的场景。就像这一刻,大家意识到MySQL无法解决大数据量的OLAP问题,必须要有专业的OLAP引擎来解决。开源社区要的不是能力全而不强的平庸软件,而是百花齐放,各有所长,通过组合实现架构协同。以上仅代表作者个人观点。欢迎广大读者有不同的看法,互相讨论。3.总结本文分别对ClickHouse的存储引擎和计算引擎进行了简要分析,得出了ClickHouse速度快的不同前提。存储引擎要求的先决条件如下。使用MergeTree存储引擎。根据业务需求,正确设置数据表的排序键,查询时必须满足最左原则。计算引擎架构要求的先决条件如下。不使用或很少使用Join操作。尽可能使用内置函数。当满足以上四个条件时,就可以使用ClickHouse来实现比较优秀的性能。作者简介:陈峰,资深大数据专家和架构师,ClickHouse技术专家,地扑科技(2B领域独角兽)合伙人兼首席架构师。《ClickHouse性能之巅:从架构设计解读性能之谜》作者。