标签:技术 矢量 整型 关系操作符 临时 使用 数据处理 列存储 两种方法
莫愁前路无知己,天下谁人不识君。
ClickHouse 是一个真正的列式数据库管理系统(DBMS)。在 ClickHouse 中,数据始终是按列存储的,包括矢量(向量或列块)执行的过程。只要有可能,操作都是基于矢量进行分派的,而不是单个的值,这被称为“矢量化查询执行”,它有利于降低实际的数据处理开销。
通常有两种不同的加速查询处理的方法:矢量化查询执行和运行时代码生成。在后者中,动态地为每一类查询生成代码,消除了间接分派和动态分派。这两种方法中,并没有哪一种严格地比另一种好。运行时代码生成可以更好地将多个操作融合在一起,从而充分利用 CPU 执行单元和流水线。矢量化查询执行不是特别实用,因为它涉及必须写到缓存并读回的临时向量。如果 L2 缓存容纳不下临时数据,那么这将成为一个问题。但矢量化查询执行更容易利用 CPU 的 SIMD 功能。ClickHouse 使用了矢量化查询执行,同时初步提供了有限的运行时动态代码生成。
要表示内存中的列(实际上是列块),需使用 IColumn
接口。该接口提供了用于实现各种关系操作符的辅助方法。几乎所有的操作都是不可变的:这些操作不会更改原始列,但是会创建一个新的修改后的列。比如,IColumn::filter
方法接受过滤字节掩码,用于 WHERE
和 HAVING
关系操作符中。另外的例子:IColumn::permute
方法支持 ORDER BY
实现,IColumn::cut
方法支持 LIMIT
实现等等。
IColumn::filter和IColumn::permute
方法作为纯虚函数,代码位于dbms\src\Columns目录下的IColumn.h中,在子类中有具体的实现,比如ColumnDecimal子类。
IColumn::cut方法在基类IColumn中实现,用于LIMIT操作。
不同的 IColumn
实现(ColumnUInt8
、ColumnString
等)负责不同的列内存布局。内存布局通常是一个连续的数组。对于数据类型为整型的列,只是一个连续的数组,比如 std::vector
。对于 String
列和 Array
列,则由两个向量组成:其中一个向量连续存储所有的 String
或数组元素,另一个存储每一个 String
或 Array
的起始元素在第一个向量中的偏移。而 ColumnConst
则仅在内存中存储一个值,但是看起来像一个列。
对于ColumnString类,Chars用于存储所有的String,offsets用于存储每个String在Chars中的偏移。代码位于dbms\src\Columns目录下的ColumnString.h和ColumnString.cpp中。
对于ColumnArray类,data用于存储数组元素,offsets用于存储每个Array在data中的偏移,代码位于dbms\src\Columns目录下的ColumnArray.h和ColumnArray.cpp中。
Column相关的代码目录位于dbms\src\Columns路径下,涉及到的类及相互关系如下图所示:
标签:技术 矢量 整型 关系操作符 临时 使用 数据处理 列存储 两种方法
原文地址:https://www.cnblogs.com/snake-fly/p/12534235.html