福利置顶(温馨提示):电子版可在微信读书app阅读。
第一章 ClickHouse的前世今生
传统BI的局限性。
数据仓库
为了解决数据孤岛的问题,即通过引入一个专门用于分析类场景的数据库,将分散的数据统一汇聚到一处。
数据仓库的衍生概念
对数据进行分层,通过层层递进形成数据集市,从而减少最终查询的数据体量;提出数据立方体的概念,通过对数据进行预先处理,以空间换时间,提升查询性能。
OLAP,联机分析,多维分析,基本操作:下钻、上卷、切片、切块、旋转。架构大致可分成三类:
- ROLAP
Relational OLAP,关系型OLAP - MOLAP
Multidimensional OLAP,多维型OLAP;维度预处理可能会导致数据的膨胀 - HOLAP
Hybrid OLAP,混合架构的OLAP
按顺序存储的数据会拥有更高的查询性能。因为读取顺序文件会用更少的磁盘寻道和旋转延迟时间(这里主要指机械磁盘),同时顺序读取也能利用操作系统层面文件缓存的预读功能,所以数据库的查询性能与数据在物理磁盘上的存储顺序息息相关。
ClickHouse适用的场景
BI商业智能、广告流量、Web、App流量、电信、金融、电子商务、信息安全、网络游戏、物联网等众多其他领域。
不适用的场景
- 不支持事务
- 不擅长根据主键按行粒度进行查询(支持),故不应该把CK当作K-V数据库使用
- 不擅长按行删除数据(支持)
第二章 ClickHouse架构概述
使用多主对等网络结构,
核心特性:
- 完备的DBMS功能
- 列式存储与数据压缩
- 向量化执行引擎
- 关系模型与SQL查询
- 多样化的表引擎
- 多线程与分布式
- 多主架构
- 在线查询
- 数据分片与分布式查询
架构设计
第三章 安装与部署
需要验证当前服务器的CPU是否支持SSE 4.2指令集,因为向量化执行需要用到这项特性。
配置文件
-
/etc/security/limits.d/clickhouse.conf
:文件句柄数量配置 -
/etc/cron.d/clickhouse-server:cron
:定时任务配置,用于恢复因异常原因中断的ClickHouse服务进程
可执行文件
主要是在/usr/bin
路径下:
- clickhouse:主程序的可执行文件
- clickhouse-client:一个指向ClickHouse可执行文件的软链接,供客户端连接使用
- clickhouse-server:一个指向ClickHouse可执行文件的软链接,供服务端启动使用
- clickhouse-compressor:内置提供的压缩工具,可用于数据的正压反解
客户端的访问接口
- TCP
基于TCP协议,拥有更好的性能,默认端口为9000,主要用于集群间的内部通信及CLI客户端; - HTTP
基于HTTP协议,拥有更好的兼容性,可以通过REST服务的形式被广泛用于JAVA、Python等编程语言的客户端,其默认端口为8123。 - 封装接口
包括CLI和JDBC,简单易用,基于TCP底层接口的封装。
CLI
有两种执行模式:
- 交互式执行
广泛用于调试、运维、开发和测试等场景,通过交互式执行的SQL语句,相关查询结果会统一被记录到~/.clickhouse-client-history
文件,可以作为审计之用。 - 非交互式执行
用于批处理场景,如对数据的导入和导出等操作,需要追加--query
参数指定SQL语句。--multiquery
参数执行多次查询,支持一次运行多条分号间隔的SQL查询语句,多条SQL的查询结果集会依次按顺序返回。
JDBC
JDBC底层基于HTTP接口通信,该驱动有两种形式:
- 常规模式:
jdbc:clickhouse://<host>:<port>[/<database>]
- 高可用模式:允许设置多个host地址,每次会从可用的地址中随机选择一个进行连接:
jdbc:clickhouse://<first-host>:<first-port>,<second-host>:<second-port>[,…][/<database>]
内置工具
- clickhouse-local
可以独立运行大部分SQL查询,不需要依赖任何ClickHouse的服务端程序,它可以理解成是ClickHouse服务的单机版微内核,是一个轻量级的应用程序。clickhouse-local只能够使用File表引擎,它的数据与同机运行的ClickHouse服务也是完全隔离的,相互之间并不能访问。非交互式运行的,每次执行都需要指定数据来源。
核心参数:
-S / --structure
:表结构
-N / --table
:表名称,默认值是table
-if / --input-format
:输入数据的格式,默认值是TSV
-f / --file
:输入数据的地址,默认值是stdin标准输入
-q / --query
:待执行SQL语句,多条语句分号间隔 - 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三类。
- String长度不限,不限定字符集,但建议遵循使用统一的编码
- FixedString,
FixedString(N)
,使用null字节填充末尾字符 - UUID,32位,它的格式为8-4-4-4-12,空值默认用0填充,即
0…0-…00
时间
时间类型分为DateTime、DateTime64和Date三类。CK目前没有时间戳类型。时间类型最高的精度是秒,即若需要处理毫秒、微秒等大于秒分辨率的时间,则只能借助UInt类型实现。
- DateTimeDateTime类型包含时、分、秒信息,精确到秒,支持使用字符串形式写入
- DateTime64DateTime64可以记录亚秒,在DateTime之上增加精度的设置
- DateDate类型不包含具体的时间信息,只精确到天,同样支持字符串形式写入
复合类型
数组、元组、枚举和嵌套
- Array
有两种定义形式
以最小存储代价为原则,即使用最小可表达的数据类型 - Tuple
元组类型由1~n个元素组成,每个元素之间允许设置不同的数据类型,且彼此之间不要求兼容。元组同样支持类型推断,其推断依据仍然以最小存储代价为原则 - Enum
包括Enum8和Enum16两种枚举类型,
Key和Value是不允许重复的,要保证唯一性。其次,Key和Value的值都不能为Null,但Key允许是空字符串。 - Nested
一种嵌套表结构。一张数据表,可以定义任意多个嵌套类型字段,但每个字段的嵌套层级只支持一级,即嵌套表内不能继续使用嵌套类型。嵌套类型本质是一种多维数组的结构。嵌套表中的每个字段都是一个数组,并且行与行之间数组的长度无须对齐。在访问嵌套类型的数据时需要使用点符号。
特殊类型
- Nullable
并不能算是一种独立的数据类型。只能和基础类型搭配使用,也不能作为索引字段。应该慎用Nullable类型,包括Nullable的数据表,不然会使查询和写入性能变慢。因为在正常情况下,每个列字段的数据会被存储在对应的[Column].bin
文件中。如果一个列字段被Nullable类型修饰后,会额外生成一个[Column].null.bin
文件专门保存它的Null值。即在读取和写入数据时,需要一倍的额外文件操作。 - Domain
域名类型,分为IPv4和IPv6两类,本质上是对整型和字符串的进一步封装。IPv4类型基于UInt32封装的,IPv6类型是基于FixedString(16)封装。如果需要返回IP的字符串形式,则需要显式调用IPv4NumToString或IPv6NumToString函数进行转换。
数据表定义
数据表操作
分区操作
目前只有MergeTree系列的表引擎支持数据分区。parts系统表专门用于查询数据表的分区信息。
- 查询:
- 删除:
ALTER TABLE table1 DROP PARTITION partition1
- 复制:可以用于快速数据写入、多表间数据同步和备份等场景;两个前提条件:两张表需要拥有相同的分区键;表结构完全相同。
- 重置:重置为初始值,
ALTER TABLE table1 CLEAR COLUMN column1 IN PARTITION partition1
,如果已声明默认值表达式,则以表达式为准;否则以相应数据类型的默认值为准 - 卸载:
ALTER TABLE table1 DETACH PARTITION partition1
,分区被卸载后,其物理数据并没有删除,而是被转移到当前数据表目录的detached子目录下,即脱离CK的管理,CK并不会主动清理这些文件,这些分区文件会一直存在。 - 装载:
ALTER TABLE table1 ATACH PARTITION partition1
,卸载的逆过程,恢复数据。 - 备份:FREEZE
- 还原: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元素定义:
第六章 MergeTree原理解析
只有合并树系列的表引擎才支持主键索引、数据分区、数据副本和数据采样这些特性,同时也只有此系列的表引擎支持ALTER相关操作。Replicated前缀,支持数据副本。
第七章 MergeTree系列表引擎
表引擎大致分成6个系列:合并树、外部存储、内存、文件、接口和其他。
数据TTL与存储策略。
数据TTL
在MergeTree中,可以为某个列字段或整张表设置TTL,如果同时设置了列级别和表级别的TTL,则会以先到期的那个为主。INTERVAL完整的操作包括SECOND、MINUTE、HOUR、DAY、WEEK、MONTH、QUARTER和YEAR。
执行optimize命令强制触发TTL清理
多路径存储策略
第八章
第九章
第十章
第十一章