Clickhouse-即席查询的利器

757 阅读6分钟

定义

高性能的OLAP的列式数据库

优势

  • 数据压缩比率大
  • 单表读写能力强
  • 多数据引擎,选择性多
  • 支持高可用

劣势

  • 不适合高qps
  • 表连接性能低
  • 自定义函数开发难度高
  • 删改能力弱

数据库排名

排名44,不算靠前,但在OALP领域里,还算不错 image.png

性能测试

我使用我的笔记本电脑的虚拟机测试的资源如下

image.png

写能力测试

image.png

读能力测试

系统负载高,性能稍微低一些,其中UserBea表一共有35168911条数据,而CityRecord表有1156831条数据

select t.day,t.visit_num,t2.sale_num from
             (select day,count(day) as visit_num from(
             select toDate(times) as day from UserBea where item_id=1
             )t
             group by day ) t left join (
             select day,count(day) as sale_num from(
             select toDate(times) as day from CityRecord where item_id=1
             )group by day)t2
             ON t2.day=t.day

image.png

ck读写性能强劲的来源

  • 高效利用cpu的并行处理的(MMP架构)
  • 高效紧凑的列式数据压缩
  • 向量化计算

数据引擎介绍

clickhouse支持多种数据引擎,如可以从mysql和hdfs读取数据,以下一一介绍

Megre Tree

Megre Tree是使用最多的数据引擎,是clickhouse的最重要的引擎

写入特点

  • 数据以数据段的形式批次写入
  • 数据段不可更改
  • 数据段定期合并

建表语法

create table t_order_mt(
id type,
name type
 ) engine =MergeTree 
 partition by name 
 primary key (id) 
 order by (id); 
sample by inthash32(id) 
setting index_granularity=8192 
  • partition by 按字段分区,可提升索引效率
  • primary key 唯一主键索引,可以不添加,默认为order by 的字段作为索引
  • order by 在数据字段指定的字段排序按照排序
  • sample by 采样方法
  • setting index_granularity 指定稀疏索引,相比之前的全部指定全部索引,采取建立少量的索引,用来 索引一定范围字段,可以减少查找索引的时间

image.png

TTL

ttl可以设定非主键列或者表的存活时间,设定格式为

指定列

#后续添加
alter table t_order_mt modify column name type ttl create_time + interval 1 day/second/minute
## 或者建表时候指定ttl时间
name  ttl create_time + interval 1 day/second/minute

指定表

create table t_order_mt(
id type,
name type
 ) engine =MergeTree 
 partition by name 
 primary key (id) 
 order by (id); 
sample by inthash32(id) 
setting index_granularity=8192 
 ttl create_time + interval 1 day/second/minute

LSM树

clickhouse使用LSM结构来查询保存数据

写入方式

Megre Tree 使用LSM tree结构保存数据。LSM树存储原理是使用多个层次的树,最上层次的树,数据最少,数据版本也是最新,每次都会写到最少一层,达到一层次后,才进行合并

image.png

数据合并方式

数据合并方式是以上一层直接覆盖下一层的相同的key,合并的层能保证全局有序

image.png 详细可以查看这篇文章

ReplacingMergeTree

ReplaingMergeTree可以保证主键唯一,避免重复数据,但需要注意的是:

  • 只能保证分区内是唯一的
  • order by的字段比primary key权重更高
  • 只能在表合并后,才能去除重复数据(按照版本号,key等标志)
#合并表
optimize table a final

SummingMerge Tree

只能查询聚合结果

AggregatingMerge Tree

类似数据立方体的概念,会预先将数据聚合成为一个cube,是一个聚合的统计的概念,统计一下表数据,字段结构如下

image.png

create table item_agg(
item_id Int64,
day Date,
num   AggregateFunction(sum,Int32),
price AggregateFunction(sum,Int32)
)engine=AggregatingMergeTree()
partition by day
order by item_id

注意:

  • 聚合是使用order by 字段
  • 合并分区才会发生聚合计算
  • 建议和物理视图搭配使用
  • 由于保存的结果为二级制,需要相应的查询语法
select item_id,day,sumMerge(num) from item_agg  group by item_id,day ;

image.png

VersionedCollapsingMergeTree

这两个引擎是用在数据修改方面,可以直接插入新的数据,可以根据版本号,保留最新版本的数据,但必须在一个分区内。

HDFS

hdfs引擎可以直接查询hdfs上的数据,建表的格式如下

create table item_agg(
item_id Int64,
day Date,
num   AggregateFunction(sum,Int32),
price AggregateFunction(sum,Int32)
)engine=HDFS('hdfs://host:9000/hive','csv')

Mysql引擎

create table t1
(
    id     Int32,
    name   String,
    createDate DateTime
)
    engine = MySQL('localhost:3306', 'demo', 'mysql_engine', 'root', '123456');

kafka引擎

建议使用kafka引擎消费kafka数据,在使用物化视图查询写入另外的表

create table t1
(
    id     Int32,
    name   String,
    createDate DateTime
)ENGINE = Kafka()
SETTINGS kafka_broker_list = 'hadoop103:9092', 
      kafka_topic_list = 'userkafka',
      kafka_group_name = 'consumer-group', 
      kafka_format = 'JSONEachRow',
      kafka_skip_broken_messages = 1,
      kafka_num_consumers = 2

参数说明:

  • kafka_skip_broken_message:解析错误跳过的条数
  • kafka_num_consumers :消费的线程数

Buffer

内存型引擎,重新将直接丢失数据

物化视图

视图是数据预聚合结果的查询,性能较高,但对源表写入不友好,需要消耗太多资源处理视图的触发器

定义

下面是物化视图的维基百科的介绍

In computing, a materialized view is a database object that contains the results of a query. For example, it may be a local copy of data located remotely, or may be a subset of the rows and/or columns of a table or join result, or may be a summary using an aggregate function.

The process of setting up a materialized view is sometimes called materialization. This is a form of caching the results of a query, similar to memoization of the value of a function in functional languages, and it is sometimes described as a form of precomputation. As with other forms of precomputation, database users typically use materialized views for performance reasons, i.e. as a form of optimization.

总结如下:物化视图是先先建立规则并优化的查询的缓存 场景如下: 为了不断更新源表的聚合记录可以使用视图,将新的记录写入

CREATE MATERIALIZED VIEW agg_mv engine=AggregatingMergeTree()
partition by day
order by (item_id,day)  POPULATE as 
select item_id , day, sumState(toInt32(1))  as num ,sumState(toInt32(price)) as price from(
select item_id ,toDate(times) as day, 1 as  num ,price
from CityRecord 

)
group by item_id,day

更新策略

1.物化视图创建好之后,若源表被写入新数据则物化视图也会同步更新 2.POPULATE 关键字决定了物化视图的更新策略: 若有POPULATE 则在创建视图的过程会将源表已经存在的数据一并导入,类似于 create table ... as 若无POPULATE 则物化视图在创建之后没有数据,只会在创建只有同步之后写入源表的数据. clickhouse 官方并不推荐使用populated,因为在创建物化视图的过程中同时写入的数据不能被插入物化视图。 3.物化视图不支持同步删除,若源表的数据不存在(删除了)则物化视图的数据仍然保留

4.物化视图是野种特殊的数据表,可以用show tables 查看