福利置顶(温馨提示):电子版可在微信读书app阅读。

第一章 ClickHouse的前世今生

传统BI的局限性。

数据仓库
为了解决数据孤岛的问题,即通过引入一个专门用于分析类场景的数据库,将分散的数据统一汇聚到一处。

数据仓库的衍生概念
对数据进行分层,通过层层递进形成数据集市,从而减少最终查询的数据体量;提出数据立方体的概念,通过对数据进行预先处理,以空间换时间,提升查询性能。

OLAP,联机分析,多维分析,基本操作:下钻、上卷、切片、切块、旋转。架构大致可分成三类:

  1. ROLAP
    Relational OLAP,关系型OLAP
  2. MOLAP
    Multidimensional OLAP,多维型OLAP;维度预处理可能会导致数据的膨胀
  3. HOLAP
    Hybrid OLAP,混合架构的OLAP

​clickhouse-benchmark-test​

按顺序存储的数据会拥有更高的查询性能。因为读取顺序文件会用更少的磁盘寻道和旋转延迟时间(这里主要指机械磁盘),同时顺序读取也能利用操作系统层面文件缓存的预读功能,所以数据库的查询性能与数据在物理磁盘上的存储顺序息息相关。

ClickHouse适用的场景
BI商业智能、广告流量、Web、App流量、电信、金融、电子商务、信息安全、网络游戏、物联网等众多其他领域。

不适用的场景

  1. 不支持事务
  2. 不擅长根据主键按行粒度进行查询(支持),故不应该把CK当作K-V数据库使用
  3. 不擅长按行删除数据(支持)

第二章 ClickHouse架构概述

使用多主对等网络结构,
核心特性:

  1. 完备的DBMS功能
  2. 列式存储与数据压缩
  3. 向量化执行引擎
  4. 关系模型与SQL查询
  5. 多样化的表引擎
  6. 多线程与分布式
  7. 多主架构
  8. 在线查询
  9. 数据分片与分布式查询

架构设计

第三章 安装与部署

需要验证当前服务器的CPU是否支持SSE 4.2指令集,因为向量化执行需要用到这项特性。

配置文件

  1. ​/etc/security/limits.d/clickhouse.conf​​:文件句柄数量配置
  2. ​/etc/cron.d/clickhouse-server:cron​​:定时任务配置,用于恢复因异常原因中断的ClickHouse服务进程

可执行文件
主要是在​​​/usr/bin​​路径下:

  1. clickhouse:主程序的可执行文件
  2. clickhouse-client:一个指向ClickHouse可执行文件的软链接,供客户端连接使用
  3. clickhouse-server:一个指向ClickHouse可执行文件的软链接,供服务端启动使用
  4. clickhouse-compressor:内置提供的压缩工具,可用于数据的正压反解

客户端的访问接口

  1. TCP
    基于TCP协议,拥有更好的性能,默认端口为9000,主要用于集群间的内部通信及CLI客户端;
  2. HTTP
    基于HTTP协议,拥有更好的兼容性,可以通过REST服务的形式被广泛用于JAVA、Python等编程语言的客户端,其默认端口为8123。
  3. 封装接口
    包括CLI和JDBC,简单易用,基于TCP底层接口的封装。

CLI
有两种执行模式:

  1. 交互式执行
    广泛用于调试、运维、开发和测试等场景,通过交互式执行的SQL语句,相关查询结果会统一被记录到​​​~/.clickhouse-client-history​​文件,可以作为审计之用。
  2. 非交互式执行
    用于批处理场景,如对数据的导入和导出等操作,需要追加​​​--query​​​参数指定SQL语句。​​--multiquery​​参数执行多次查询,支持一次运行多条分号间隔的SQL查询语句,多条SQL的查询结果集会依次按顺序返回。

JDBC

<dependency>
<groupId>ru.yandex.clickhouse</groupId>
<artifactId>clickhouse-jdbc</artifactId>
<version>0.2.4</version>
</dependency>

JDBC底层基于HTTP接口通信,该驱动有两种形式:

  1. 常规模式:​​jdbc:clickhouse://<host>:<port>[/<database>]​
  2. 高可用模式:允许设置多个host地址,每次会从可用的地址中随机选择一个进行连接:​​jdbc:clickhouse://<first-host>:<first-port>,<second-host>:<second-port>[,…][/<database>]​

内置工具

  1. clickhouse-local
    可以独立运行大部分SQL查询,不需要依赖任何ClickHouse的服务端程序,它可以理解成是ClickHouse服务的单机版微内核,是一个轻量级的应用程序。clickhouse-local只能够使用File表引擎,它的数据与同机运行的ClickHouse服务也是完全隔离的,相互之间并不能访问。非交互式运行的,每次执行都需要指定数据来源。
    核心参数:
    ​​​-S / --structure​​​:表结构
    ​​​-N / --table​​​:表名称,默认值是table
    ​​​-if / --input-format​​​:输入数据的格式,默认值是TSV
    ​​​-f / --file​​​:输入数据的地址,默认值是stdin标准输入
    ​​​-q / --query​​:待执行SQL语句,多条语句分号间隔
  2. clickhouse-benchmark
    基准测试的小工具,会给出QPS、RPS(Request Per Second)、各百分位的查询执行时间,可以指定多条SQL进行测试,此时需要将SQL语句定义在文件中。
    核心参数:
    ​​​-i / --iterations​​​:SQL查询执行的次数,默认值是0
    ​​​-c / --concurrency​​​:同时执行查询的并发数,默认值是1
    ​​​-r / --randomize​​​:在执行多条SQL语句时,按照随机顺序执行
    ​​​-h / --host​​​:服务端地址,默认值是localhost。支持对比测试,此时需要声明两个服务端的地址,在对比测试中,会通过抽样的方式比较两组查询指标的差距
    ​​​--confidence​​:设置对比测试中置信区间的范围,默认值是5(99.5%),取值有0(80%)、1(90%)、2(95%)、3(98%)、4(99%)和5(99.5%)。

第四章 数据定义

数据类型

包括基础类型、复合类型和特殊类型

基础类型

基础类型只有数值、字符串和时间三种类型,没有Boolean类型,可使用整型的0或1替代。

数值类型

数值类型分为整数、浮点数和定点数三类

字符串

可以细分为String、FixedString和UUID三类。

  1. String长度不限,不限定字符集,但建议遵循使用统一的编码
  2. FixedString,​​FixedString(N)​​,使用null字节填充末尾字符
  3. UUID,32位,它的格式为8-4-4-4-12,空值默认用0填充,即​​0…0-…00​
时间

时间类型分为DateTime、DateTime64和Date三类。CK目前没有时间戳类型。时间类型最高的精度是秒,即若需要处理毫秒、微秒等大于秒分辨率的时间,则只能借助UInt类型实现。

  1. DateTimeDateTime类型包含时、分、秒信息,精确到秒,支持使用字符串形式写入
  2. DateTime64DateTime64可以记录亚秒,在DateTime之上增加精度的设置
  3. DateDate类型不包含具体的时间信息,只精确到天,同样支持字符串形式写入

复合类型

数组、元组、枚举和嵌套

  1. Array
    有两种定义形式
    以最小存储代价为原则,即使用最小可表达的数据类型
  2. Tuple
    元组类型由1~n个元素组成,每个元素之间允许设置不同的数据类型,且彼此之间不要求兼容。元组同样支持类型推断,其推断依据仍然以最小存储代价为原则
  3. Enum
    包括Enum8和Enum16两种枚举类型,
    Key和Value是不允许重复的,要保证唯一性。其次,Key和Value的值都不能为Null,但Key允许是空字符串。
  4. Nested
    一种嵌套表结构。一张数据表,可以定义任意多个嵌套类型字段,但每个字段的嵌套层级只支持一级,即嵌套表内不能继续使用嵌套类型。嵌套类型本质是一种多维数组的结构。嵌套表中的每个字段都是一个数组,并且行与行之间数组的长度无须对齐。在访问嵌套类型的数据时需要使用点符号。

特殊类型

  1. Nullable
    并不能算是一种独立的数据类型。只能和基础类型搭配使用,也不能作为索引字段。应该慎用Nullable类型,包括Nullable的数据表,不然会使查询和写入性能变慢。因为在正常情况下,每个列字段的数据会被存储在对应的​​[Column].bin​​文件中。如果一个列字段被Nullable类型修饰后,会额外生成一个​​[Column].null.bin​​文件专门保存它的Null值。即在读取和写入数据时,需要一倍的额外文件操作。
  2. Domain
    域名类型,分为IPv4和IPv6两类,本质上是对整型和字符串的进一步封装。IPv4类型基于UInt32封装的,IPv6类型是基于FixedString(16)封装。如果需要返回IP的字符串形式,则需要显式调用IPv4NumToString或IPv6NumToString函数进行转换。

数据表定义

数据表操作

分区操作

目前只有MergeTree系列的表引擎支持数据分区。parts系统表专门用于查询数据表的分区信息。

  1. 查询:
  2. 删除:​​ALTER TABLE table1 DROP PARTITION partition1​
  3. 复制:可以用于快速数据写入、多表间数据同步和备份等场景;两个前提条件:两张表需要拥有相同的分区键;表结构完全相同。
  4. 重置:重置为初始值,​​ALTER TABLE table1 CLEAR COLUMN column1 IN PARTITION partition1​​,如果已声明默认值表达式,则以表达式为准;否则以相应数据类型的默认值为准
  5. 卸载:​​ALTER TABLE table1 DETACH PARTITION partition1​​,分区被卸载后,其物理数据并没有删除,而是被转移到当前数据表目录的detached子目录下,即脱离CK的管理,CK并不会主动清理这些文件,这些分区文件会一直存在。
  6. 装载:​​ALTER TABLE table1 ATACH PARTITION partition1​​,卸载的逆过程,恢复数据。
  7. 备份:FREEZE
  8. 还原:FETCH

分布式DDL执行

将一条普通的DDL语句转换成分布式DDL执行十分简单,只需加上​​ON CLUSTER cluster_name​​声明即可。这意味着在集群中任意一个节点上执行DDL语句,集群中的每个节点都会以相同的顺序执行相同的语句。

数据写入、删除与修改

三种形式:
1.
2.

第五章 数据字典

数据字典是一种非常简单、实用的存储媒介,它以键值和属性映射的形式定义数据。字典中的数据会主动或者被动(数据是在ClickHouse启动时主动加载还是在首次查询时惰性加载由参数设置决定)加载到内存,并支持动态更新。字典数据常驻内存,非常适合保存常量或经常使用的维度表数据,以避免不必要的JOIN查询。

分为内置与扩展两种形式。内置字典是CK默认自带字典,而外部扩展字典是用户通过自定义配置实现的字典。在正常情况下,字典中的数据只能通过字典函数访问(CK特别设置一类字典函数,专门用于字典数据的取用)。例外:使用特殊的字典表引擎。在字典表引擎的帮助下,可以将数据字典挂载到一张代理的数据表下,从而实现数据表与字典数据的JOIN查询。

内置字典

目前只有一种内置字典——Yandex.Metrica字典,默认情况下禁用,需要开启后才能使用。开启它的方式也十分简单,只需将​​config.xml​​​文件中​​path_to_regions_hierarchy_file​​​和​​path_to_regions_names_files​​两项配置打开。这两项配置是惰性加载的,只有当字典首次被查询的时候才会触发加载动作。填充Yandex.Metrica字典的geo地理数据由两组模型组成,可以分别理解为地区数据的主表及维度表

外部扩展字典

目前扩展字典支持7种类型的内存布局和4类数据来源,以插件形式注册。
在默认的情况下,CK会自动识别并加载​​​/etc/clickhouse-server​​​目录下所有以​​_dictionary.xml​​结尾的配置文件。同时CK也能够动态感知到此目录下配置文件的各种变化,并支持不停机在线更新配置文件。在单个字典配置文件内可以定义多个字典,其中每一个字典由一组dictionary元素定义:

<dictionaries>
<dictionary>
</dictionary>
</dictionaries>

第六章 MergeTree原理解析

只有合并树系列的表引擎才支持主键索引、数据分区、数据副本和数据采样这些特性,同时也只有此系列的表引擎支持ALTER相关操作。Replicated前缀,支持数据副本。

第七章 MergeTree系列表引擎

表引擎大致分成6个系列:合并树、外部存储、内存、文件、接口和其他。
数据TTL与存储策略。

数据TTL
在MergeTree中,可以为某个列字段或整张表设置TTL,如果同时设置了列级别和表级别的TTL,则会以先到期的那个为主。INTERVAL完整的操作包括SECOND、MINUTE、HOUR、DAY、WEEK、MONTH、QUARTER和YEAR。
执行optimize命令强制触发TTL清理

多路径存储策略

第八章

第九章

第十章

第十一章