优点
- 灵活的MPP架构 支持线性扩展 简单方便 高可靠性
- 多服务器分布式处理数据 完备的DBMS系统
- 底层数据列式存储 支持压缩 优化数据存储 优化索引数据 优化底层存储
- 容错跑分快 比Vertica快5倍 比Hive快279倍 比MySQL快800倍 其可处理的数据级别已达到10亿级别
- 功能多 支持数据统计分析各种场景 支持类SQL查询 异地赋值部署
- 海量数据存储 分布式运算 快速闪电的性能 几乎实时的数据分析 友好的SQL语法 出色的函数支持
缺点
- 不支持事务 不支持真正的删除/更新(批量)
- 不支持高并发 官方建议qps为100 可以通过修改配置文件增加连接数 但是在服务器足够好的情况下
- 不支持二级索引
- 不擅长多表join
- 元数据管理需要人为干预
- 尽量做1000条以上批量的写入 避免逐行insert或小批量的insert update delete操作
应用场景
- 绝大多数请求都是用于读访问的 要求实时返回结果
- 数据需要以大批次(大于1000行)进行更新 而不是单行更新 或者根本没有更新操作
- 数据只是添加到数据库 没有必要修改
- 读取数据时 会从数据库中提取出大量的行 但只用到一小部分列
- 表很”宽” 即表中包含大量的列
- 查询频率相对较低(通常每台服务器每秒查询数百次或更少)
- 对于简单查询 允许大约50毫秒的延迟
- 列的值是比较小的数值和短字符串(例如 每个URL只要60个字节)
- 在处理单个查询时需要高吞吐量(每台服务器每秒高达数十亿行)
- 不需要事务
- 数据一致性要求较低[原子性 持久性 一致性 隔离性]
- 每次查询中只会查询一个大表 除了一个大表 其余都是小表
- 查询结果显著小于数据源 即数据有过滤或聚合 返回结果不超过单个服务器内存大小
引擎
不同的引擎决定了表数据的存储特点 位置和表数据的操作行为
- 决定表存储在哪里以及以何种方式存储
- 支持哪些查询以及如何支持
- 并发数据访问
- 索引的使用
- 是否可以执行多线程请求
- 数据是否存储副本
表引擎决定了数据在文件系统中的存储方式 常用的也是官方推荐的存储引擎是MergeTree系列 如果需要数据副本的话可以使用ReplicatedMergeTree系列 相当于MergeTree的副本版本 读取集群数据需要使用分布式表引擎Distribute
clickhouse是分布式数据库(单节点可以工作)
存储引擎
- 不同的引擎决定数据存储的位置
- 数据存储的方式 行式 列式 有索引 没有索引 有压缩 没有压缩
- 查询的速度 操作方式
- 是否支持并发操作
Log引擎
存储在本地磁盘
每个字段 一个文件 列式
每个属性 一个单独的文件 每次插入都是追加
数据存储在指定的表目录下 /var/lib/clickhouse/data/….
Memory 数据存储在内存
表引擎(即表的类型)决定了:
- 数据的存储方式和位置 写到哪里以及从哪里读取数据
- 支持哪些查询以及如何支持
- 并发数据访问
- 索引的使用(如果存在)
- 是否可以执行多线程请求
- 数据复制参数 是否可以存储数据副本
- 分布式引擎 实现分布式
Log系列引擎
Log家族具有最小功能的[轻量级]引擎 当您需要快速写入许多小表(最多约100万行) 并在以后整体读取它们时 该类型的引擎是最具有效的
TinyLog引擎
最简单的表引擎 用于将数据存储在磁盘上 每列都存储在单独的压缩文件中 写入时 数据将附加到文件末尾 该引擎没有并发控制
- 最简单的引擎
- 没有索引 没有标记块
- 写是追加写
- 数据以列字段文件存储
- 不允许同时读写
StripeLog引擎
- data.bin存储所有数据
- index.mrk 对数据建立索引
- size.json数据大小
- 并发读写
Log引擎
Log与TinyLog的不同之处在于 标记的小文件与列文件存在一起 这些标记写在每个数据块上 并且包含偏移量 这些偏移量指示从哪里开始读取文件以便跳过指定的行数 这使得可以在多个线程中读取表数据 对于并发数据访问 可以同时执行读取操作 而写入操作则阻塞读取和其它写入 Log引擎不支持索引 同样 如果写入表失败 则该表将被破坏 并且从该表读取将返回错误 Log引擎适用于临时数据 write-once 表以及测试或演示目的
- *.bin存储每个字段的数据
- mark.mrk数据块标记
- 支持多线程处理
- 并发读写”
Log和StripeLog引擎支持:
并发访问数据的锁
INSERT请求执行过程中表会被锁定 并且其他的读写数据的请求都会等待直到锁定被解除 如果没有写数据的请求 任意数量的读请求都可以并发执行
并行读取数据
在读取数据时 ClickHouse使用多线程 每个线程处理不同的数据块
Log引擎为表中的每一列使用不同的文件 StripeLog将所有的数据存储在一个文件中 因此StripeLog引擎在操作系统中使用更小的描述符 但是Log引擎提供更高的读性能
TinyLog引擎是该系列中最简单的引擎并且提供了最小的功能和最低的性能 TinyLog引擎不支持并行读取和并发数据访问 并将每一列存储在不同的文件中 它比其余两种支持并行读取的引擎的读取速度更慢 并且使用了和Log引擎同样多的描述符 你可以在简单的低负载的情景下使用它
MergeTree引擎
MergeTree在写入一批数据时 数据总会以数据片段的形式写入磁盘 且数据片段不可修改 为了避免片段过多 ClickHouse会通过后台线程 定期合并这些数据片段 属于相同分区的数据片段会被合成一个新的片段 这种数据片段往复合并的特点 也正是合并树名称的由来
MergeTree表引擎处理常规参数之外 还拥有一些独有的配置选项 接下来会着重介绍其中几个重要的参数
- PARTITION BY[选填] 分区键 用于指定表数据以何种标准进行分区 分区键既可以是单个列字段 也可以通过元组的形式使用多个字段 同时它也支持使用列表达式 如果不声明分区键 则ClickHouse会生成一个名为all的分区 合理使用数据分区 可以有效 减少查询时数据文件的扫描范围
- ORDER BY[必填]:排序键 用于指定在一个数据片段内 数据以何种标准排序 默认情况下主键(PRIMARY KEY)与排序键相同 排序键既可以是单个列字段 例如ORDER BY CounterID 也可以通过元组的形式使用多个列字段 例如 ORDER BY 当使用多个列字段排序时 以ORDER BY 为例 在单个数据片段内 数据首先会以CounterID排序 相同CounterID的数据再按EventDate排序
- PRIMARY KEY[选填]:主键 顾名思义 声明后会依照主键字段生成一级索引 用于加速表查询 默认情况下 主键与排序键(ORDER BY)相同 所以通常直接使用ORDER BY代为指定主键 无须刻意通过PRIMARY KEY声明 所以在一般情况下 在单个数据片段内 数据与一级索引以相同的规则升序排序 与其他数据库不同 MergeTree主键允许存在重复数据(ReplacingMergeTree可以去重)
- SAMPLE BY[选填]:抽样表达式 用于声明数据以何种标准 进行采样 如果使用了此配置项 那么在主键的配置中也需要声明同样的表达式
ReplacingMergeTree
这个引擎是在MergeTree的基础上 添加了”处理重复数据”的功能 该引擎和MergeTree的不同之处在于它会删除具有相同(区内)排序一样的重复项 数据的去重只会在合并的过程中出现 合并会在未知的时间在后台进行(手动合并) 所以你无法预先做出计划 有些数据可能仍未被处理 因此 ReplacingMergeTree适用于在后台清除重复的数据以节省空间 ‘但是它不保证没有重复的数据出现
- 使用ORDER BY排序键作为判断重复数据的唯一依据
- 只有在合并分区的时候才会触发删除重复数据的逻辑
- 以数据分区为单位删除重复数据 当分区合并时 同一分区内的重复数据会被删除 不同分区之间的重复数据不会被删除
- 在进行数据去重时 因为分区内的数据已经基于ORDER BY进行了排序 所以能找到那些相邻的重复数据’
- 使用这个引擎可以 实现数据的更新
CollapsingMergeTree
CollapsingMergeTree就是一种通过以增代删的思路 支持行级数据修改和删除的表引擎 它通过定义一个sign标记位字段 记录数据行的状态 如果sign标记为1 则表示这是一行有效的数据 如果sign标记为-1 则表示这行数据需要被删除
