背景:俄罗斯的yandex公司于2016年开源,C++项目,使用sql操作
主要用于在线分析查询(OLAP) 一次插入,多次查询
特点:开源数据库,简单,查询快,增删改慢
为什么快?
举个例子
行式存储如在磁盘中的存储方式是:
1 张三 五岁 2 李四 五岁 3 王麻子 六岁
列式存储在磁盘中的存储方式是:
1 2 3 张三 李四 王麻子 五岁 五岁 六岁
列式存储操作
列式存储可以直接找到位置,获取某一段
列如:查询名称,直接查出
但是增删改时,就需要
在三个位置上修改数据,所以慢,
行式存储操作
增删改,只要找到位置,就可以直接操作,插入
查询,需要一个一个罗列,慢
综上所属,所以(clickhouse)列式存储,适用于聚合,计数,求和等操作,适合渲染图表。
高吞吐写入能力
clickhouse采用类LSM tree结构,数据写入后,定期在后台合并(Compation)
顺序写,提高6000倍的效率
数据分区与线程级并行
clickHouse非常消耗CPU,单条query就能利用整机所有的CPU,对于高gps(每秒查询次数)的场景不适用
多样化引擎
ClickHouse有多种引擎,可以根据不同的需求设定不同的存储引擎,目前包括合并树,日志,接口和其他四大类20多种引擎。
在建表时必须指定表引擎,表引擎指定了如何存储表的数据,包括
1.数据的存储方式和位置,写到哪里以及从哪里读取数据
2.支持哪些查询以及如何支持
3.并发数据访问
4.所引的使用(如果存在)
5.是否可以执行多线程请求
6.数据复制参数
引擎的名称大小写敏感(驼峰式)
TingLog引擎
以列的行时保存在磁盘上,不支持索引,没有并发控制,一般保存少量数据的小表,自己做一些测试时用
建表语句
create table t_tinglog(id string,name string)engine=TinyLog
Memory引擎
内存引擎,数据以未压缩的原始形式直接保存在内存中,服务重启数据会消失,不支持索引,简单查询有非常高的性能,超过10G/秒
重点:MergeTree引擎(系列)
ClickHouse中最强大的表引擎,支持索引和分区,衍生ReplacingMergeTree和SummingMergeTree
ClickHouse中,主键不是唯一的,是可以重复的,order by是建表必须的,engine指定引擎,partition by指定分区条件,不指定就一个分区,每个分区的文件都单独放在不同的分区目录中
create table text( id UInt32, text_id String, name String, text_amount Decimal(16,2), create_time Datetime )engine=MergeTree partition by toYYYYMMDD(create_time) primary key(id) order by(id,text_id)
并行:分区后,面对涉及跨分区的查询统计,ClickHouse会以分区为单位进行处理
应用了稀疏索引,主键之间,默认分割8192条数据
order by排序中,主键要排在前面
二级索引:在稀疏索引下,再次稀疏索引一次,为了再首次稀疏索引下查询有二异性下,分割粒度
命令:INDEX a text_amount TYPE minmax GRANULARITY 5
create table text( id UInt32, text_id String, name String, text_amount Decimal(16,2), create_time Datetime, INDEX a text_amount TYPE minmax GRANULARITY 5 )engine=MergeTree partition by toYYYYMMDD(create_time) primary key(id) order by(id,text_id)
控制合并命令
optimize table 表名 final
查最终的数据
select * from 表名 final
ReplacingMergeTree
是MergeTree的一个变种,存储特性完全继承MergeTree,多了一个去重功能,不是事实的,需要在合并的时候去除
保证最终的一致性
去重范围,分区内
engine=ReplacingMergeTree(create_time)
在create_time最大的值保存
不指定,保留最后插入的数据
SummingMergeTree
聚合合并树,分区内预聚合,不是实时的,合并时更新
engine=SummingMergeTree(字段) 必须为数字字段
根据order by指定的字段来进行聚合,按SummingMergeTree指定的字段,进行聚合
使用场景,一个用户多次购买物品,算总数
更新和删除(对事务提供简介操作)重操作
alert table 表名 delete where 条件
alert table 表名 update 改的数据 where 条件
更新和删除会建立一个新的分区,之后再合并这个分区,所以更新和删除的操作复杂耗费资源,操作重
实现高性能update或delete思路
create table A( a xxx, b xxx, c xxx, _sign Uint, // _sign, 0 未删除,1已删除 _version UInt32; )
修改用插入代替:插入一条新的数据,_version + 1
查询时加上一个过滤条件 where version最大
删除用插入代替: _sign=1,_version + 1
查询的时候加上条件 where _sign=0 and _version最大
时间久,数据膨胀,合并时,要处理过期数据
副本,需要使用zookeeper支撑(协调者)
无主从之分,副本,在MergeTree等引擎前加Replicated
engine=ReplicatedMergeTree('/clickhouse/tale/01/表名','rep_02')
第一个路径是zookeeper的路径,后面是副本名字
副本名称不一样
分片
需要一个Distributed表引擎,不存储数据,通过分布式逻辑来写入,分发,路由来操作多台节点不同分片的分布式数据
ClickHouse的集群是表级别的,大多数企业用了副本实现高可用,但是不适用分片
原因:避免降低查询性能和操作的复杂性
create table text on cluster gmall_cluster( id UInt32, text_id String, name String, text_amount Decimal(16,2), create_time Datetime, )engine=ReplicatedMergeTree('/clickhouse/tables/{shard}/text','{replica}') partition by toYYYYMMDD(create_time) primary key(id) order by(id,text_id)
gmall_cluster:配置文件中的集群名称
shard:配置文件中,分片配置
replica:配置文件中,副本配置
create table text_all on cluster gmall_cluster( id UInt32, text_id String, name String, text_amount Decimal(16,2), create_time Datetime, )engine=Distributed(gmall_cluster,default,text,hiveHash(text_id));
Distributed(分布式表)中不放入数据,向分区中插入数据,根据text_id的hash判断放入那个分区
gmall_cluster:集群名称
default:库名
text:本地表名
hiveHash:分片键
向st_order_mt_all2中插入数据,实现分片和副本
查看执行计划(执行时间,确认问题和调优用)
新版本支撑Explain
20.6版本之后支持
可以查看执行流程
可以优化sql
Explain syntax sql语句
老版本
clickhouse-client -h 主机名 --send_log_level=trace