目录
TinyLog:以列文件的形式保存在磁盘上,不支持索引,没有并发控制,一般存储少量数据。
MergeTree是以列文件+索引文件+表定义文件组成。linux下,clickhouse的所有文件都存放在/var/lib/clickhouse/下,
并行:分区后,对涉及到跨区查询的处理,clickhouse会进行并行处理
是MergeTree的一个变种,存储过程完全继承mergeTree,增加了去重功能。
学习背景:
学习背景:目前一直在做BI相关,我们的指标表数据量随之时间推移不断上升,导致查服务越来越慢。问题产生,我老大@Michael Gu见招拆招,提到了clickhouse列式存储数据库,聚合性能非常优秀,纵然mysql的索引也非常强大,但是在数据量大的情况下也有些吃力,因此对它深度学习,便于以后迁移数据。
提示:clickhouse官网:https://clickhouse.com/docs/zh/
数据结构:
注:数字代表位数
-  有符号整型- int8:【与java的byte类型范围一致】
- int16:【与java的short类型范围一致】
- int32:【与java的int类型范围一致】
- int64:【与java的long类型范围一致】
 
-  无符号整型- Uint8:【0~2^8-1】
- Uint16:【0~2^16-1】
- Uint32:【0~2^32-1】
- Uint64:【0~2^64-1】
 
-  浮点型- float32:java中的float
- float64:java中的double。金钱相关的不要用float,要用decimal
 
-  布尔- 没有单独存放布尔的数据类型,但是可以用int8,0和1来代表
 
-  Decimal(金额相关的)- decimal32:相当于decimal(9-s,s),例如:decimal(5),整数加小数一共9位,小数点后5位,不会四舍五入。
- decimal64:相当于decimal(18-s,s),同上。
- decimal128:相当于decimal(38-s,s),同上。
 
-  字符串- String:同java
- FixedString(N):当字符串的字节长度不为N的时候,会向字符串的右边补空字节来达到N长度。
 
-  enum枚举类型- 用来保存:String和Integer的对应关系。
 
-  时间类型:- date:年月日
- dateTime:年月日时分秒
- dateTime64:年月日时分秒亚秒
 
-  Array(T):数组类型- T类型元素组成的数组
- 对二维数组支持的不太好
- 用法:array('1','2')。或者['1','2'],类型必须一致,不然会报错。
 
-  Nullable(数据类型):- 使用null会对性能产生影响,可以使用业务中无意义的数据进行代替。'' or -1 or 'null'。
 
表引擎作用:
- 管理数据的存储方式,例如:不能在merge Tree中存储多维数组。写到哪里以及从哪里读区取 例如:本地path:var/lib/clickHouse/。同时也可以集成hadoop和kafka,那么此时,数据就在远程。
- 支持哪些查询以及如何支持。
- 支持并发数据访问,线程级的并行。
- 对索引的支持。
- 支持多线程的请求。
- 数据复制参数
- 注意:引擎的名称大小写敏感。
所有的表引擎及其特点
-  TinyLog:以列文件的形式保存在磁盘上,不支持索引,没有并发控制,一般存储少量数据。- 生产环境作用不大。
 
-  Memory:- 基于内存,快,不靠谱,重启后数据消失,读写不会阻塞,不支持索引,简单查询有非常高的性能。
 
-  MergeTree:ClickHouse中最牛逼的存储引擎-  MergeTree# 建表语句与mysql类似,注意分区字段,它也可以有主键(主键不一定唯一,可以重复),同时也会创建索引。 CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster] ( name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1], name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2], ... ) ENGINE = VersionedCollapsingMergeTree(sign, version) [PARTITION BY expr] [ORDER BY expr] [SAMPLE BY expr] [SETTINGS name=value, ...] # order by字段是必须的。 # 具体的字段解释官网有解释:https://clickhouse.com/docs/zh/engines/table-engines/mergetree-family/versionedcollapsingmergetree/
-  部分关键字解析:- partition by:分区字段,避免全表扫描,缩小范围,优化查询速度。注意,不要使用错误最终只产生一个分区。分区的本质就是分目录。
 
-  MergeTree是以列文件+索引文件+表定义文件组成。linux下,clickhouse的所有文件都存放在/var/lib/clickhouse/下,- 我们需要关心两个文件,data:存放数据的文件。metadata:表结构文件。
-  
      文件名称 文件作用 bin文件 数据文件 mrk文件:标记文件 在索引文件和数据文件之前起到了桥梁的作用 primary.idx文件 主键索引文件,加快执行效率 min_max_create_time 分区键的最大最小值 checksums 检验文件的正确性 
 
-  并行:分区后,对涉及到跨区查询的处理,clickhouse会进行并行处理
-  数据写入和分区合并-  同一批次插入的数据会产生一个临时分区,不会并入任何一个分区中,写入后的某个时刻,clickhouse才会将插入的文件合并到已有分区中。 
-  强制合并命令: -  optimize table [表名] final,强制合并表数据。 
-  optimize table partition '分区名' final,强制合并表数据。 
 
-  
 
-  
-  primary_key主键索引:-  主键可以包含多个列。 
-  没有唯一约束:意味着可以重复,平时主键放在where条件中。 
-  它是稀疏索引,类似于redis的跳表。优点:索引的数据量小,配合索引粒进行二分查找,避免全表扫描。 
-  索引粒官方默认为为8192,可以打开一个库,通过 show create table [表名] 就可以查看到。修改的场景为:几万条数据的id都是重复的,好几万个1,那么此时创建的稀疏索引没有意义。 
 
-  
-  order by(可以是多个字断)-  创建表必写,分区内进行排序,如果不排序,稀疏索引无法找数。 
-  order by的字段必须是主键的前缀,且不能跳过一个字段。 
 
-  
-  二级索引/跳数索引-  创建方式:在所有的字段后面加。在一级索引上再次组索引段。 INDEX [给当前索引的命名] [当前索引使用的字段] TYPE [minmax] GRANULARITY 粒度值 
-  二级索引的作用: -  保证在id重复的时候也能更好的确定范围,提升查询速度 
 
-  
 
-  
-  数据TTL-  可以对表或列设置其存活时间,对离线场景作用不大,适合于实时场景,例如:最新数据进行用户画像。 
-  字段创建方式 -  在需要进行TTL的字段后面追加:TTL [数据的创建时间且数据的创建时间必须为DateTime类型且这个列不能为主键id] + interval [阈值] [SECOND/MINNUTE/DAY/WEEK/YEAR/YEAR/MONTH/HOUR]。时间单位具体的请看clickhouse官网表引擎方面。 
 
-  
-  表的创建方式: -  alter table 表名 MODIFY TTL [数据的创建时间且数据的创建时间必须为DateTime类型且这个列不能为主键id] + interval [阈值] [SECOND/MONTH/HOUR] 
 
-  
-  时间到期后的动作: -  delete 默认行为 
-  move to disk ‘aaa’ 
 
-  
 
-  
 
-  
-  ReplacingMergeTree-  是MergeTree的一个变种,存储过程完全继承mergeTree,增加了去重功能。-  
      MergeTree ReplacingMergeTree primary key 可以重复,不具备唯一约束 功能。 根据order by的字段进行去重 
 
-  
      
-  去重时机- 只有在合并的时候才会进行去重,合并数据的时机是未知的,所以只能保证数据的最终一致性。
 
-  去重范围-  只能在分区范围内进行去重,不能执行跨分区的去重。 
 
-  
-  建表语句-  CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster] ( name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1], name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2], ... ) ENGINE = ReplacingMergeTree([ver]) [PARTITION BY expr] [ORDER BY expr] [SAMPLE BY expr] [SETTINGS name=value, ...]
- ENGINE = ReplacingMergeTree([ver]) 
      - 括号里的内容是重复时该保留哪条数据的依据,如果传入了字段,以最大的作为保留,如果没有声明,则以最后插入的进行保留,相当于版本控制工具。
 
 
-  
 
-  
-  SummingMergeTree- 更擅长于做聚合场景,如果使用普通的mergeTree的话,对存储空间的开销和临时聚合的开销都是比较大的。
- SummingMergeTree是进行预聚合的一种引擎,预聚合的时机为合并数据时。且只能在本分区内进行聚合。
- 建表语句 
    -  CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster] ( name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1], name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2], ... ) ENGINE = SummingMergeTree([columns]) 注意:columns必须是数值类型 [PARTITION BY expr] [ORDER BY expr] [SAMPLE BY expr] [SETTINGS name=value, ...]
 
-  
- 在同一批次插入的才会被聚合,在插入完毕并合并的那一刻已经聚合好了。
- 开发建议: 
    - 设计聚合表的话,流水号,唯一键可以去掉,只保留聚合维度,也就是手动指定聚合列。
- 虽然引擎帮咋们做了预聚合,但是,sql语句该怎么写还是要怎么写的,但是根据他的特性,还是有部分数据没有聚合进去, select sum(*) from table where **。
 
 
-  各种引擎的使用带来的一些问题- 数据幂等性问题(定时任务执行一半失败,重启定时任务,第二次全量插入完成) 
    - 重复写入带来的数据重复问题,采用ReplacingMergeTree,但是用了这个引擎并不能彻底的解决这个问题,如果分两波合并(注:去重操作会在合并过程中执行,合并时机未知),还是会出现数据不一致问题。再者,线上操作合并不现实,且是否会影响到业务。
 
 
- 数据幂等性问题(定时任务执行一半失败,重启定时任务,第二次全量插入完成) 
    
-  ClickHouse的sql与标准sql不一样的地方-  Insert语法基本相同
-  关注Update和Delete语法- update和delete被称为Mutation查询,该操作支持 MergeTree系列表,包含支持复制功能的表。可以看作是alter的一种,Mutation是一种很重的操作,且不支持事务,重的原因在他会放弃数据原有的分区,重建分区,一段时间后再合并分区,所以最好一次批量变更好,不要频繁的进行小数量的变更。
- 删除 
      -  ALTER TABLE [db.]table DELETE WHERE filter_expr;
 
-  
-  更新 -  ALTER TABLE [db.]table UPDATE column1 = expr1 [, ...] WHERE filter_expr;
 
-  
 
- update和delete被称为Mutation查询,该操作支持 
-  select-  支持子查询 
-  支持with子句,相当于一张临时表。 
-  支持各种join,但是join无法使用缓存,尽量避免使用join,下面是join的工作原理: -  单节点的数据片 
-  
-  分布式的数据片 
-  
-  针对这种情况: -  我们mysql/hive的join,是小表驱动大表。 
-  但是在clickhouse中,如果要小表驱动大表,内存会超出限制,导致语句都跑不完。 
 
-  
 
-  
 
-  
-  严格来讲,clickhouse不适合做upsert-  用别的方案也可以作为代替,比如说版本号,或者标记字段。 
 
-  
-  对函数的支持- 官网的函数文档:简介 | ClickHouse文档,非常清晰全面。
 
-  group by增加了一些语句- with rollup:上卷  
      
- with cube :多维分析,将group by 的字段进行更细粒度的划分 
      
- with total:总计
- 使用方式:正常语句后进行追加对应的单词即可
 
- with rollup:上卷  
      
-  Alter语法与Mysql一致- 新增字段
- 修改字段类型:注意 小转大可以,但是大转小不行。
- 删除字段
 
-  副本- 保障数据的高可用,及时一台clickhouse宕机,也可以从别的节点获取数据。
 
- 互为副本,目的是去中心化,但是并没有解决数据的横向扩容,也就是分布式的数据分片。
- 要解决分布式的数据分片问题,需要引入Distributed表引擎把数据拼接在一起进行使用。但是并不是所有的企业都只会进行副本保障高可用,不会进行数据分片,目的是为了避免降低查询性能以及减少操作集群的复杂性。
- 读取过程 
      
- 写入过程 
      
 
 
-  
-  集成的其他引擎:- mysql,mongo,RabbitMq,相当于打通一个通道,省区了数据导入的过程。
- 例:mysql引擎的使用可以访问官网来进一步了解https://clickhouse.com/docs/zh/engines/database-engines/mysql/
 






 
  







