面试官:相比于MySQL,你觉得ClickHouse牛在哪儿?

数据库 MySQL
bloom_filter索引,顾名思义,是用来构建布隆过滤器的,默认有0.025(可调整)的误差率,会将原本不存在的值误认为已存在。但用在二级索引上是不影响正确性的,仅仅是多查询了一些数据块而已。

有时候真的挺替MySQL鸣不平的,被最广泛地应用在各个系统中,却当着Redis、ES、Oracle的背景板,挨着最狠地骂。

嗯,今天又拿它跟OLAP数据库ClickHouse进行比较了。

一般来讲,90%多的Java工程师是接触不到ClickHouse的,而用到它的最大原因,无非是拿MySQL硬抗海量数据的统计分析类的场景实在太吃力了,临战换将成ClickHouse之后,顿觉世界时如此美好。

接下来我们就来说说,ClickHouse到底有多牛逼,以及牛逼在哪儿。

对比数据

在一系列官方公布的基准测试对比中,ClickHouse都遥遥领先对手,这其中不乏一些我们耳熟能详的名字。

所有用于对比的数据库都使用了相同配置的服务器,在单个节点的情况下,对一张拥有133个字段的数据表分别在1000万、1亿和10亿三种数据体量下执行基准测试,基准测试的范围涵盖43项SQL查询。

在1亿数据集体量的情况下,ClickHouse的平均响应速度是Vertica的2.63倍、InfiniDB的17倍、MonetDB的27倍、Hive的126倍、MySQL的429倍以及Greenplum的10倍。

下图也是ClickHouse官网上公布的测试数据:

图片图片

接下来我们具体分析一下,ClickHouse到底具备那些特性,以至于它比MySQL的性能高出如此之多。

MPP架构

ClickHouse采用典型的MPP(Massively Parallel Processing)架构,直译为大规模并行处理架构,可将任务并行的分散到多个节点上,每个节点各自独立完成自己的计算任务,然后将各节点的处理结果进行二次加工汇总,形成最终的结果进行返回。

如下图所示:

图片图片


MPP架构中的各个计算节点相互独立,具备高性能和易扩展的优点,可在海量数据下实现高吞吐量和低延迟的数据处理能力。

而MySQL InnoDB本身是不具备分布式并行计算能力的,一般情况下都是用分库分表中间件进行实现的,也有少部分是直接在工程代码中进行实现。

当然,从完善度和平滑性来讲,肯定是不如ClickHouse的一体化解决方案的。

列式存储

假设这样的一个业务场景,一张有2000多万条记录的people表,我们需要计算出表中所有人的平均年龄。

如下图所示:

图片图片

对MySQL InnoDB存储引擎比较熟悉的同学都知道,其存储结构是按照表空间(tablespace)——>段(segment)——>区(extent)——>page(页)的方式进行组织的,而page是MySQL InnoDB的最小IO单元,默认为16k。

而page中存储的才是MySQL InnoDB的行记录(row),每行记录中有若干个列字段值。

如下图所示:

图片图片

那么,对于MySQL InnoDB存储引擎的行式数据库来说,如果需要计算people全表的平均年龄,那就需要以page为IO单元全表扫描出所有数据,再把里面的age数据挑出来进行计算,才能得出最终的结果。

而Clickhouse的存储形式则完全不一样了,它是以数据列的方式进行组织存储的,每个列字段都拥有独立的.bin数据文件,并以列字段的名称命名。

如下图所示:

图片图片

如果需要计算people全表的平均年龄的话,ClickHouse只需要读取age.bin文件中的数据进行计算即可。

这样一来,假设people表中有20个字段,对于计算出表中所有人的平均年龄的需求,ClickHouse所需要读取的数据量只有MySQL InnoDB的大约1/20,那自然想性能不高都难。

我们来看一下,ClickHouse官网对于行式存储和列式存储的对比配图,还是比较形象的。

行式存储:

图片图片

列式存储:

图片图片


数据压缩

由于压缩后的数据不仅可以节省存储空间,还可以减少磁盘IO和网络传输的数据量,这是高性能数据库必不可少的特性。

并且,ClickHouse列式数据库比MySQL InnoDB存储引擎的行式数据库,对数据压缩更加友好。

原因在于,在ClickHouse最常用的MergeTree表引擎中,数据表中的同一列数据是保存在一个文件里的,其拥有相同的数据类型和业务语义,重复项的可能性自然就很高。比如:订单金额、个人年龄、工作收入等。

而重复项越高,文件压缩率和数据体量就越小,也就越能减少磁盘IO和网络传输的压力。

ClickHouse默认使用LZ4算法进行数据压缩的,压缩比可以达到8:1。

再来说说MySQL InnoDB,可以通过如下SQL语句进行数据压缩,但压缩效果一般,仅可以节省30%到50%的磁盘空间。

ALTER TABLE sbtest1 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8

并且通过性能测试得知,数据压缩对数据库服务器的负载和CPU使用率影响较大,在性能上也并无提升。

这样看来,MySQL InnoDB的数据压缩仅能节省有限的磁盘空间,效果比较鸡肋。

向量化执行引擎

像Flink、Spark、Storm这些分布式计算框架,会将一个大任务拆解成若干个可以并行执行的小任务,以此来提升整体的任务处理吞吐量。

而ClickHouse为了最大限度地将CPU的性能压榨到极致,实现了向量化执行引擎,其核心思想是充分利用现代处理器的并行处理能力,来提升代码执行效率。

向量化执行引擎可以对一组数据执行相同的一个指令,在访问速度最快的寄存器层面实现单指令、多数据(SIMD )操作,以实现空间上的并行。

各硬件访问速度对比,如下图:

图片图片

SIMD操作方式,如下图:

图片图片

索引设计

ClickHouse与MySQL InnoDB的索引设计方式截然不同,它的一级索引是采用稀疏索引的方式进行实现的。

对比如下:

图片图片


在上图左侧的稠密索引中,索引标记和数据记录是一一对应的,而图右侧的稀疏索引则对应的是包含N行记录的一个数据块。

稀疏索引的优点是,仅需要少量索引标记就可以记录海量数据的区间位置信息。如果索引粒度是默认的8192,那一亿条数据仅需要对应12208个索引标记,这样就可以将索引标记放到内存中,可以起到提升查询性能的效果。

在二级索引方面,MySQL InnoDB只支持B+ Tree和Hash两种类型,而ClickHouse则支持minmax、set、bloom_filter、ngrambf_v1、tokenbf_v1和inverted等索引类型。

minmax索引,用来记录N(N = granularity)个数据块内的最大值和最小值,在对某列数据进行范围查询的时候,可以过滤掉不满足条件的数据区间,其适用于数据区分度比较高的场景。

如下图所示:

图片图片

set索引,用来记录每个数据块中的不重复值,举个例子,如果该数据块所对应的列中有8000个1,190个2,1个3和1个4,那set中所记录的值就是(1,2,3,4)。

set索引的适用场景为,在区分度低的列上查找列值很少的数据行。比如:在订单表中查询状态为“退款”的订单。

bloom_filter索引,顾名思义,是用来构建布隆过滤器的,默认有0.025(可调整)的误差率,会将原本不存在的值误认为已存在。但用在二级索引上是不影响正确性的,仅仅是多查询了一些数据块而已。

责任编辑:武晓燕 来源: 托尼学长
相关推荐

2015-08-13 10:29:12

面试面试官

2019-07-23 16:00:36

区块链存储5G

2011-12-12 13:09:45

云计算

2022-02-25 10:03:11

对象数据算法

2013-12-04 09:33:15

软件成本

2015-08-27 13:45:25

2022-03-25 10:22:48

TransformeAI机器学习

2023-06-07 15:29:33

MySQL事务面试

2014-04-17 10:16:50

2023-09-12 11:38:18

2018-05-21 10:11:43

2022-07-01 06:03:08

WiFi 7WiFi 6

2021-03-16 07:13:07

Java对象存储

2024-04-02 09:45:27

线程池Executors开发

2019-04-24 16:40:18

Redis数据库

2013-05-10 10:58:56

ERP

2020-03-25 09:20:21

自然语言处理

2024-10-12 16:25:12

2021-08-09 07:47:40

Git面试版本

2021-11-25 10:18:42

RESTfulJava互联网
点赞
收藏

51CTO技术栈公众号