Clickhouse 计算引擎架构 —— Clickhouse 架构篇(三)

文章目录

前言

相比较于存储引擎的精妙设计,ClickHouse的计算引擎一直是一个争议非常大的话题。对ClickHouse计算引擎的各种评价都有,两极分化很严重。有人认为ClickHouse计算引擎的向量化设计得巧夺天工,也有很多人认为ClickHouse的计算引擎缺乏优化和对分布式的支持,就是个半成品。这些对ClickHouse计算引擎的评价都在一定程度上反映了ClickHouse计算引擎的某些方面,如果从这些方面来看待ClickHouse的计算引擎,难免陷入盲人摸象的状态。

本文将介绍ClickHouse计算引擎的架构,以及ClickHouse的向量化计算引擎与传统事务数据库的火山引擎之间的区别。整体了解ClickHouse计算引擎后,我们将客观地得出自己对ClickHouse计算引擎的评价。

ClickHouse计算引擎的架构简介与设计思想

传统计算引擎会将 SQL 转换为物理计划,Clickhouse 也一样, Clickhouse 将物理计划叫做查询流水线(QueryPipeline)。

架构简介

整体架构

ClickHouse计算引擎整体架构如下图所示,由三部分组成:SQL解析器(Parser)、解释器(Interpreter)、执行器(PipelineExecutor)。

ClickHouse计算引擎整体架构是按照火山引擎的模式进行设计的,将SQL语句转化为可以被执行的处理单元(Processor)的集合,由执行器执行。向量化引擎和火山引擎最大的不同点在于ClickHouse的处理单元的设计是面向向量的,而传统事务数据库是面向行的。构成QueryPipeline的处理单元不同,导致ClickHouse计算引擎和传统的火山模型的不同。这也是ClickHouse向量化引擎的由来。

SQL解析器

  • Clickhouse 中的 SQL 解析器并没有使用传统的开源方案,而是自己手写的,但是 SQL 解析在整个查询中的耗时可以忽略不计。

解释器

  • Clickhouse 解释器会根据 AST 树生成查询流水线,该阶段会对SQL 进行逻辑优化,ClickHouse中实现的逻辑优化主要是基于规则进行优化,常用的手段有谓词下推、count优化、消除重复字段等。

执行器

  • ClickHouse通过执行器对查询流水线进行处理,最终获得结果即为用户提交的SQL语句的执行结果。
  • ClickHouse的高性能来自向量化引擎。向量化引擎的核心在于查询流水线的编排方式,火山模型和向量化模型的本质区别在于SQL语句的编排方式。

设计思想

Clickhouse 的所有架构设计都是为了一个目标:充分发挥单机能力的OLAP引擎

充分利用现代CPU特性

  • 向量化引擎利用了现代CPU提供的SIMD能力,提供的硬件加速能力。

充分发挥单机优势

  • Clickhouse 中的表都是对单机表的操作,Clickhouse 中的集群表并不是真正意义上类似于 Hadoopz 中的分布式表,而是单机表的映射。

    因此 Clickhouse 中的 SQL 对大表 JOIN 操作,经常由于内存不足导致失败,Clickhouse 的更多架构设计放在了向量化引擎上。

  • 我们在使用 Clickhouse 查询时应该尽量避免 JOIN 操作,充分发挥向量化引擎的特性。

火山模型

ClickHouse的向量化引擎是基于标准火山模型进行的调整。

火山模型执行示意图如下,一般经历三个过程,扫描,过滤,投影 ,每一个过程都会返回一个元组 ,执行完毕后调用 next() 方法,进入下一过程计算。

  • 扫描(Scan)节点负责从磁盘中读取所有member表的数据并交给过滤(Select)节点。
  • 过滤节点负责过滤出满足过滤条件的数据并交给投影(Project)节点。
  • 投影节点负责将表中birthday列的数据筛选出来,再按照用户提供的计算公式计算出Age并返回给用户。
  • 过滤指的是按行筛选,投影指的是按列筛选。

火山模型的核心是有很多独立的算子,每个算子计算出一个元组,然后每个算子又是一个迭代器,通过 next() 方法调用下一个算子。例如Join操作,在火山引擎中表现为一个Join迭代器,在其next方法中实现Join操作的各种算法,返回元组,供上层进一步操作。再如OrderBy操作,在火山引擎中也会表现为一个OrderBy迭代器,在其next方法中将输入的数据按照规则进行排序,并向上输出元组供上层使用。
优点

  • 通过堆叠不同节点的方式实现能力,因此在实现火山引擎时只需要实现有限数量的计算节点,且每个节点只需要实现单一的简单功能,即可完成模型的构建。

缺点

  • 可能导致堆叠的层数过多,甚至出现大量的递归操作,从而降低查询性能。

向量化引擎

向量化引擎是在火山引擎的基础上实现的,火山引擎每一个算子返回的是元组,由不同的列组成,而向量化引擎返回的是单独列组成的数组,也被称为列向量

向量化引擎的实现方式

火山引擎和向量化引擎的物理计划执行对比如下图:

向量化引擎列向量的设计,可以使投影操作将下推至扫描阶段,在第一步扫描阶段直接返回birthday列。最终,该SQL语句的执行顺序如下:

  1. 通过读取数据源(ReadFromSource)节点直接获得birthday列向量。
  2. 通过过滤转换(FilterTransform)节点筛选出满足isVip=1的数据。
  3. 通过表达式转换(ExpressionTransform)节点计算出Age。

将投影操作下推至底层阶段,可以在表中列的数量比较多的场景下获得很高的性能。

另外,向量化引擎可以使用向量化的算法进行计算,充分利用CPU并行计算的特性,实现计算加速。

向量化引擎的前提

既然向量化计算可以并行计算,提升查询性能,为何传统的事物数据库不使用向量化计算呢?

下边让我们看下向量化引擎的前提。
存储引擎支持

  • 向量化引擎产生效果的前提是存储引擎返回的数据是按列聚集的,而事物数据库一般是行存,对于行存的存储引擎来说,设计向量化的计算引擎没有必要。除非事务数据库能够抛弃传统的行存存储引擎,改用列存储引擎。
  • 即使改为列存,事物数据库的核心是事物性,列存的存储引擎在应对事务时会带来更多的额外工作,导致事务的性能急剧下降,得不偿失。

硬件支持

  • 需要 CPU 支持 SIMD 向量化计算,软件只是将组织好的数据交给硬件,真正执行向量化计算的还是 CPU。

软件支持

  • 这里的软件特指编译器和向量化算法。编译器会自动将符合向量化优化的操作编译为特殊的SIMD指令。

计算引擎如何影响查询速度

Clickhouse 的向量化引擎可以利用向量化计算大大加速查询速度,但是凡事有利有弊,Clickhouse 在解释器阶段生成物理计划的时候,并没有进行 CBO(代价优化器)优化物理计划,只有逻辑计划的优化,导致对于有些 SQL 场景反而查询速度很慢,甚至失败。

因此在使用 Clickhouse 进行查询时,我们也需要注意一些事项,充分发挥向量化计算的优势。

大量使用向量化运算

  • 尽可能使用ClickHouse提供的内置函数进行计算,而不是自己写SQL 计算语句。

查询语句中没有使用Join子句,或尽可能少地使用Join操作

  • 在使用ClickHouse时,应当尽可能避免Join操作。
  • ClickHouse在设计良好的DW层上运行向量化查询的性能最高,尽可能避免将ClickHouse用于ODS层的建模工作中。当数据量大时,这类建模工作还是尽可能下推到Spark上进行。

总结

作为用户,我们应该了解ClickHouse速度快的前提,有意识地避开ClickHouse的雷区,不要将ClickHouse用于其不擅长的场景。正如此时此刻,大家都意识到了MySQL无法解决大数据量的OLAP问题,这类问题要通过专业的OLAP引擎解决。

开源社区要的并不是什么能力都有、但都不强的平庸的软件,而是百花齐放、各自有着各自擅长的领域的产品,通过组合实现架构上的合力。

相关推荐
期待着20134 天前
ClickHouse创建分布式表
数据库·clickhouse
昨天今天明天好多天4 天前
【ClickHouse】创建表
数据库·clickhouse·oracle
从未完美过5 天前
clickhouse自增id的处理
数据库·clickhouse
sunny052965 天前
ClickHouse数据库SSL配置和SSL连接测试
数据库·clickhouse·ssl
东皋长歌5 天前
ClickHouse创建账号和连接测试
clickhouse
gengjianchun8 天前
clickhouse 安装配置
服务器·网络·clickhouse
东皋长歌8 天前
ClickHouse安装
clickhouse
大嘴吧Lucy8 天前
实战攻略 | ClickHouse优化之FINAL查询加速
数据库·mysql·clickhouse
东皋长歌8 天前
SpringBoot+ClickHouse集成
clickhouse·springboot
从未完美过8 天前
ClickHouse集成Mysql表引擎跨服务器读表说明
服务器·mysql·clickhouse