1、不支持事务(OLAP不太care)
clickhouse不支持事务 ACID,无隔离级别。
对于update和delete的使用方式是采用异步方式进行的,可以在mutations表查看执行状态进度。
2、存储引擎(牛逼)
从列存来看的话,clickhouse的优势是对于上亿单表group by的聚合的响应速度很快,以及表关联join也很迅速;
但有个需要注意的点:就是如果返回的结果比较大,比如是轻度汇总的程序超过了当前查询节点单机内存,就会无法查询
(当然这个场景比较特殊,几乎不会出现查询结果就几十个G的情况)。
clickhouse 官网有详细举例的,支持17种的存储引擎,
和大多数其他数据库类似,clickhouse的存储引擎的指定也是在建表的时候来指定的,常用的有如下几种:
1.Merge Tree 系列引擎(核心引擎)
Replicated相关是支持数据副本的
其余几种有各自的用途
ReplacingMergeTree:在后台数据合并期间,对具有相同排序键的数据进行去重操作。
SummingMergeTree:当合并数据时,会把具有相同主键的记录合并为一条记录。根据聚合字段设置,该字段的值为聚合后的汇总值,非聚合字段使用第一条记录的值,聚合字段类型必须为数值类型。
AggregatingMergeTree:在同一数据分区下,可以将具有相同主键的数据进行聚合。
CollapsingMergeTree:在同一数据分区下,对具有相同主键的数据进行折叠合并。
VersionedCollapsingMergeTree:基于CollapsingMergeTree引擎,增添了数据版本信息字段配置选项。在数据依据ORDER BY设置对数据进行排序的基础上,如果数据的版本信息列不在排序字段中,那么版本信息会被隐式的作为ORDER BY的最后一列从而影响数据排序。
GraphiteMergeTree:用来存储时序数据库Graphites的数据。
CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster] ( name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1] [TTL expr1], name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2] [TTL expr2], ... ) ENGINE = MergeTree()--click的看家本领,核心引擎 ORDER BY expr [PARTITION BY expr] [PRIMARY KEY expr] [SAMPLE BY expr] [TTL expr [DELETE|TO DISK 'xxx'|TO VOLUME 'xxx'], ...] [SETTINGS name=value, ...
2.Distributed 引擎
ENGINE =Distributed(cluster_name, database, table, [sharding_key])
分布式引擎本身不存储数据,查询的时候执行分布式计算
一对多得映射式被动写入,做转发查询计算用
查询,作为中间件,类似于MapReduce的实时版,分发任务后再聚合结果返回给用户
在这里引入了分布式分片的概念,[sharding_key]就是作为分布表的分片键,会根据它的值随机打乱在集群中计算。
最常用的场景是ReplicatedMergeTree+Distributed,来实现表级别的高可用。
3、tinylog和 log 引擎
1、不支持在这类表上建立索引
2、写表的时候不能读,读了表就崩了sql会报错;
3、tinylog模式对于并发写不适用
4、Memory引擎
1、存储于单机内存中,所以表必须小于单机内存
2、重启服务器,数据直接清空、所以一般是中间表。
3、对于并发来讲,无锁访问
Clickhouse表引擎种类多,很复杂,对开发人员要求高,要找到适合的场景。存储引擎的选择决定了:
数据如何存储,如何读取查询
并发访问能力
是否支持索引
是否支持多线程请求
数据如何同步
总体来讲是很厉害的,如果一个系统只是做汇聚的上层报表,列式数据库的性能优势就会非常明显,但也不是全能。
但是对于需要取出绝大部分字段的明细宽表场景不太适用,尤其是对于一些select * 的展示场景就不太好。
比如对上百个字段的自助分析报表,现在做客户的营销,很多都要做到手机号码全维度融合明细级别。
比如多维度的分析查询场景,也许多个主题域要汇聚在一起同时展示;所以纯列式存储在获取非少数列的场景上并不是很适合。
常见的OLAP系统不适用场景:自助分析明细,客户画像标签,等等
3、迁移问题(不友好)
clickhouse对于oracle,mysql等标准sql的语法兼容性太差,也就会导致迁移起来非常的困难,语法改写太复杂。
@1 先从DML语句说起:
update,delete的标准SQL语法不支持;在clickhouse数据库里面管这两个操作叫突变,意味着这并不属于常规操作。
语法是这个样子的:
ALTER TABLE [db_name.]table_name DELETE WHERE filter_expr
举例删除操作:ALTER TABLE partition_v2 DELETE WHERE ID ='xxx'
举例更新操作: ALTER TABLE test_update UPDATE status = ‘A’ where status = ’B’
只要语句执行成功,没有语法错误,会了立即返回的结果: 0 rows in set, 为什么是0呢?
0的含义其实说明他还没有完成更新的任务,因为clickhouse的update和delete是这个是异步处理的 ,且无法回滚。
这个操作可以查看突变操作表中的记录 Select * from system.mutations where table='xxxx'
异步含义是:异步是接取一个任务,直接给后台,在接下一个任务,一直一直这样,谁的先读取完先执行谁的。
缺点:没有顺序 ,谁先读取完先执行谁的 ,会出现上面的代码还没出来下面的就已经出来了,会报错;
让我们试想一个非常常见场景,先对某表进行了update 操作,下面根据update操作后对表结果产生的变更数据,在进行和其他表的关联和生成一个新表。
因为update是异步的,且没有事务,我们也并不清楚目前数据库的忙闲状态。这个时候我们想使用表的新数据去做下一步操作的时候就必须先去字典表突变表mutations里面去查询我是否以及完成了
@2 再来说DDL的建表语法:
与标准建表语法不太一致,不是标准的DDL建表语法。举例感受一下
– 先建立一个本地表
CREATE TABLE testdb.ch_agent_user( agentname String )
ENGINE = MergeTree()
PARTITION BY agentname
ORDER BY (agentname);
– 把本地表映射到分布式表
CREATE TABLE testdb.ch_agent_dist_user AS testdb.ch_agent_user
ENGINE = Distributed(‘report_shards_replicas’, ‘testdb’, ‘ch_agent_user’, cityHash64(agentname));
– int类型标签表
CREATE TABLE testdb.es_user_feature_int( labelname String, labelvalue String, bm AggregateFunction( groupBitmap, UInt64 ) ) ENGINE = AggregatingMergeTree()
PARTITION BY labelname
ORDER BY (labelname, labelvalue);
4、去O背景下的其他语法支持问题总结
@1NULL不支持
@2各种函数完全不同。几乎全部函数都有不同的名字,有兴趣可以google看下常用的。
而且ClickHouse 数据是强类型. 类似于java和javascript中的数值类型的区别
而且最关键的是它不能在类型之间进行隐式转换.,所以需要写大量类似to_number,to_char这样的转换函数
当然在clickhouse的语法是 toFloat32OrZero() ;toInt8OrZero();toString()等等
@3子查询在FROM,IN,JOIN子句中支持
标量子查询支持(写在select后面的子查询不允许)
关联子查询不支持(exists不支持)
@4 在实际迁移过程中碰到了有一些古老的代码,左右关联是(+),都不是使用的left join和right join
5、数据库设计对象适配方面
clickhouse还不支持存储过程
clickhouse还不支持开窗函数
clickhouse还不支持树形查询
clickhouse支持普通视图和物化视图
clickhouse支持表分区 PARTITION BY和分片Distributed (分布式集群)
6、高可用
clickhouse擅长用在互联网业务不复杂的大数据量场景,通过Zookeeper进行分布式扩展,Replicated多副本进行数据复制。(对zk强依赖,扩展很难,初期集群规模一定要搭建好!再加节点就麻烦了)
一般不会像OLTP一样去做高可用容灾,数据量太大,存储是个问题,不太会需要备份容灾机制。
7、clickhouse是开源的
目前版本更新还是挺快的,但是仍然不太好用,新版本已经支持了sql执行计划的查看。但仍需要投入很强的DBA运维团队实力+开发人员才可以用的好,
主要的技术社区是俄语,大部分bug要去GitHub提问,中文社区无人问津,出现问题搜索不到。
8、其他常见问题
@1数据会重复,这个几乎很难避免,只能在应用层去避免,比如去重后计算,或者写入时去重。想精确计算还是很难的,需要准确计算的业务不要用。
@2和spark、flink等组件结合比较方便;可以引用HDFS外部表
@3接入mysql数据库比较方便,有CDC工具,比如cannal,maxwell等,可以不用flume读binglog在通过kafka等复杂方式。




