1.概述

最近有被留言关于ClickHouse的使用问题,今天笔者将为大家分享一下ClickHouse的安装细节和使用方法。

2.内容

首先安装环境如下所示:

  • Linux:CentOS7
  • ClickHouse:21.8.10.19

2.1 ClickHouse是什么?

ClickHouse是一个真正的列式数据库管理系统,在ClickHouse中,数据始终是按照列来进行存储的,包括矢量(向量或者列块)执行的过程。只要有可能,操作都是基于矢量进行分派的,而不是单个的值,这被称为矢量化查询执行,它有利于降低实际的数据处理开销。

这个想法并不新鲜,矢量编程被大量用于科学数据处理中。即使在关系型数据库中,这个想法也不是什么新的东西。通常有两种不同的加速查询处理的方法:矢量化查询执行和运行时代码生成。在后者中,动态的为每一类查询生成代码,消除了间接分派和动态分派。这两种方法中,并没有哪一种严格地比另一种好。运行时代码生成可以更好的将多个操作融合在一起,从而充分利用CPU执行单元和流水线。矢量化查询执行不是特别使用,因为它涉及必须写到缓存并读回的临时向量。如果L2缓存容纳不下临时数据,那么这将成为一个问题,但是矢量化查询执行更加容易利用CPU。

2.2 列

要表示内存中的列(实际上是列块),需使用 IColumn 接口。该接口提供了用于实现各种关系操作符的辅助方法。几乎所有的操作都是不可变的:这些操作不会更改原始列,但是会创建一个新的修改后的列。比如,IColumn::filter 方法接受过滤字节掩码,用于 WHERE 和 HAVING 关系操作符中。另外的例子:IColumn::permute 方法支持 ORDER BY 实现,IColumn::cut 方法支持 LIMIT 实现等等。
不同的 IColumn 实现(ColumnUInt8、ColumnString 等)负责不同的列内存布局。内存布局通常是一个连续的数组。对于数据类型为整型的列,只是一个连续的数组,比如 std::vector。对于 String 列和 Array 列,则由两个向量组成:其中一个向量连续存储所有的 String 或数组元素,另一个存储每一个 String 或 Array 的起始元素在第一个向量中的偏移。而 ColumnConst 则仅在内存中存储一个值,但是看起来像一个列。

2.3 字段

尽管如此,有时候也可能需要处理单个值。表示单个值,可以使用 Field。Field 是 UInt64、Int64、Float64、String 和 Array 组成的联合。IColumn 拥有 operator[] 方法来获取第 n 个值成为一个 Field,同时也拥有 insert 方法将一个 Field 追加到一个列的末尾。这些方法并不高效,因为它们需要处理表示单一值的临时 Field 对象,但是有更高效的方法比如 insertFrom 和 insertRangeFrom 等。
Field 中并没有足够的关于一个表(table)的特定数据类型的信息。比如,UInt8、UInt16、UInt32 和 UInt64 在 Field 中均表示为 UInt64。

2.4 数据类型

IDataType 负责序列化和反序列化:读写二进制或文本形式的列或单个值构成的块。IDataType 直接与表的数据类型相对应。比如,有 DataTypeUInt32、DataTypeDateTime、DataTypeString 等数据类型。
IDataType 与 IColumn 之间的关联并不大。不同的数据类型在内存中能够用相同的 IColumn 实现来表示。比如,DataTypeUInt32 和 DataTypeDateTime 都是用 ColumnUInt32 或 ColumnConstUInt32 来表示的。另外,相同的数据类型也可以用不同的 IColumn 实现来表示。比如,DataTypeUInt8 既可以使用 ColumnUInt8 来表示,也可以使用过 ColumnConstUInt8 来表示。
IDataType 仅存储元数据。比如,DataTypeUInt8 不存储任何东西(除了 vptr);DataTypeFixedString 仅存储 N(固定长度字符串的串长度)。
IDataType 具有针对各种数据格式的辅助函数。比如如下一些辅助函数:序列化一个值并加上可能的引号;序列化一个值用于 JSON 格式;序列化一个值作为 XML 格式的一部分。辅助函数与数据格式并没有直接的对应。比如,两种不同的数据格式 Pretty 和 TabSeparated 均可以使用 IDataType 接口提供的 serializeTextEscaped 这一辅助函数。

2.5 块

Block 是表示内存中表的子集(chunk)的容器,是由三元组:(IColumn, IDataType, 列名) 构成的集合。在查询执行期间,数据是按 Block 进行处理的。如果我们有一个 Block,那么就有了数据(在 IColumn 对象中),有了数据的类型信息告诉我们如何处理该列,同时也有了列名(来自表的原始列名,或人为指定的用于临时计算结果的名字)。
当我们遍历一个块中的列进行某些函数计算时,会把结果列加入到块中,但不会更改函数参数中的列,因为操作是不可变的。之后,不需要的列可以从块中删除,但不是修改。这对于消除公共子表达式非常方便。
Block 用于处理数据块。注意,对于相同类型的计算,列名和类型对不同的块保持相同,仅列数据不同。最好把块数据(block data)和块头(block header)分离开来,因为小块大小会因复制共享指针和列名而带来很高的临时字符串开销。

3.安装ClickHouse

在Github上搜索ClickHouse,并下载二进制安装包,下载内容如下:

ClickHouse实战-LMLPHP

 下载地址如下:

https://github.com/ClickHouse/ClickHouse/releases

安装步骤如下:

## 第1步
# 解压common包
tar -zxvf clickhouse-common-static-21.8.10.19.tgz
tar -zxvf clickhouse-common-static-dbg-21.8.10.19.tgz

# 执行脚本安装
sudo doinst.sh

## 第2步
# 解压server包
tar -zxvf clickhouse-server-21.8.10.19.tgz

# 修改config.xml存储路径和监听端口
<!-- 实际数据存储路径,建议用一个磁盘空间较大的目录 -->
<path>/appcom/clickhouse/data/</path>
<tmp_path>/appcom/clickhouse/data/tmp/</tmp_path>

<!-- 开启远程访问 -->
<listen_host>::</listen_host>

# 执行脚本安装
sudo doinst.sh

## 第3步
# 解压client包
tar -zxvf clickhouse-client-21.8.10.19.tgz

# 执行脚本安装
sudo doinst.sh

## 第4步
# 启动ClickHouse
/etc/init.d/clickhouse-server start

## 第5步
# 启动Client
clickhouse-client -m -h 127.0.0.1 --user default --port 9000 --password ckxxx
11-01 03:06