ClickHouse原理解析与应用实践

ClickHouse架构概述


ClickHouse架构概述

  • ClickHouse架构概述
  • 一、OLAP的架构
  • 二、OLAP技术的演进
    • ROLAP
    • MOLAP
    • 搜索引擎
    • CLickHouse
  • 三、实时聚合还是预先聚合?
  • 四、clickhouse适合的场景
  • 五、ClickHuse不适合的场景
  • 六、clickhouse的核心特性
  • 七、clickhouse数据类型
    • 基础数据类型
      • 数值型
        • int
        • Float
        • Decimal
      • 字符串类型
        • String
        • FixedString
        • UUID
      • 时间类型
        • DateTime
        • Datetime64
        • Date
      • 复合类型
        • Array
        • tuple
        • enum
        • nested
      • 特殊类型
        • nullable
        • Domain
  • 八、数据库
    • Ordinary:默认引擎
    • DIctionary 字典引擎
    • Memory 内存引擎
    • 日志引擎
    • Mysql引擎
  • 分区表
    • 查询分区信息
    • 删除分区
    • 复制分区
  • 数据写入
  • 数据删除
  • 视图
  • 数据字典
    • 内部字典
    • 外部扩展字典
    • name
    • suructure
      • 键值key
      • attribute
    • layout
      • flat
      • hashed
      • range_hashed
    • source
      • 文件类型
      • 数据库类型
    • lifetime
      • 定时更新
      • 实时更新
  • MergeTree原理解析
    • 数据分区
    • 数据TTL
    • ReplacingMergeTree
    • summingMergeTree
    • AggregatingMergeTree
    • CollapsingMergeTree
    • VersionedCollapsingMergeTree
  • 其他表引擎
    • 外部存储类型
        • hdfs
        • MySQL


一、OLAP的架构

1.ROLAP:
创建事实表维度表和指标表,使用关联的方式进行sql关联,优点是灵活,缺点是数据量大以后,查询压力很大
2.MOLAP
预计算方式,在查询前提前将聚合的结果进行预计算处理,使用空间换取时间,缺点:占用空间,会有2的n次方组合;优点:速度快
3.HOLAP
等于MOLAP+ROLAP

二、OLAP技术的演进

ROLAP

由最开始的MySQL、oracle演变成Hadoop生态体系的hive;以spark分布式计算引擎查询,响应速度还是很慢。

MOLAP

依托MapReduce和spark进行预计算,将数据结果存入HBASE等高性能分布式数据库。响应速度很快,但是存在维度爆炸,数据同步实时性问题。

搜索引擎

另辟蹊径,使用Elasticsearch搜索引擎来实现数据的聚合查询,在百万级数据的时候完全可以实现,但是数据量大后,力不从心。

CLickHouse

具有ROLAP、在线实时查询、完整的DBMS、列存储、不需要预计算、批量更新、完善的sql和函数支持、不需要Hadoop的生态,开箱即用、支持高可用。

三、实时聚合还是预先聚合?

预先聚合的问题:
预先聚合只能支持固定的分析场景,所以无法满足自定义分析的需求。
维表组合会导致数据膨胀,造成不必要的计算和存储开销。
实时数据是实时接收的,预计算还要考虑如何进行实时更新数据。
实时聚合:
实时聚合虽然是完美但是意味着一切计算都是要动态、实时的。很难做到在极短的时间内返回数据。

四、clickhouse适合的场景

在存储数据超过20万亿行的情况下,clickhouse能做到90%的查询在一秒内实现
随着数据量的正大,它的优势会更加明显。

五、ClickHuse不适合的场景

不支持事务
不擅长根据主键按着行粒度进行查询
不擅长删除数据

六、clickhouse的核心特性

列式存储和数据压缩
向量化执行引擎
关系模型和sql查询
多样化表引擎
多线程和分布式
多主架构
数据分片、分布式查询

七、clickhouse数据类型

基础数据类型

数值型

整数、浮点数、定点数

int

常见的int(tinyint、Samallint、Int、BigInt)
clickhouse中的int类型(Int8/Int16/Int32、Int64)

ClickHouse原理解析与应用实践_第1张图片
Clickhouse支持无符号的数据(UInt8、UInt16、Uint32、Uint64)
ClickHouse原理解析与应用实践_第2张图片

Float

常见是Float 代表单精度浮点数、double代表 双精度浮点数
clickhouse(Float32、Float64)
ClickHouse原理解析与应用实践_第3张图片

Decimal

定点数
clickhouse(DEcimal132、Decimal164、Decimal1128)
ClickHouse原理解析与应用实践_第4张图片

字符串类型

String

代替传统的varchar、text、clob、Blob;string类型不限定字符集,可以存储任意编码,但是为了统一UTF-8约定

FixedString

类似Char、但是和char不同的是char通常是用空格填充、FixedString是用null字节填充

UUID

常见的数据类型,如果

时间类型

clickhouse目前没有时间戳类型,也就是最高精度是秒。如果想要毫秒、微妙只能借助Uint类型

DateTime

包含年月日时分秒,支持字符串的形式写入

Datetime64

可以纪录亚秒,比如‘2022-02-02 00:00:00.00’

Date

精确到天,支持字符串写入

复合类型

Array

同一类型
select array(1,2)

tuple

可以存储1到n个元素,允许不同的数据类型。

select tuple(-1,1,‘a’,now(),today()) as a ,toTypeName(a)
“(-1,1,‘a’,‘2023-03-13 09:44:43’,‘2023-03-13’)”,“Tuple(Int8, UInt8, String, DateTime, Date)”

定义表字段的时候,需要指明元素的类型,

create table tuple_test (
c1 Tuple(String,Int8)
) engine =Memory;
insert into tuple_test values ((‘a’,1))

主要是用来保障数据质量。

enum

主要是定义常量包含(enum8 /enum16)

create table enum_test (
c1 ENUM8(‘one’=1,‘two’=2)
) engine =Memory;
insert into enum_test values (‘one’)

如果新增没有的值会报错

enum 和String的区别是:enum可以使用value进行排序分组去重

nested

嵌套类型,只支持一层

create table nested_test (
name String,
age Int8,
dept Nested(
id String,
name String
)
) engine =Memory;

对于简单的层级关系和关联关系使用嵌套类型是不错的选择

insert into nested_test values (‘zs’,18,[‘dept1’,‘dept2’],[‘deptName1’,‘deptName2’]) ;

每个字段都是需要一个数组,每个数组个数要一致。
访问嵌套的类型

select dept.id

特殊类型

nullable

create table nested_test (
name Nullable(String),
age Int8
) engine =Memory;

是一个辅助的类型,需要和基础数据类型一起搭配使用。
只能和基础数据搭配使用,不能用于数组和元祖这些符合类型,也不能用在索引字段
nullable 会让查询和写入的性能变慢

Domain

域名类型分为IPv4和IPv6

八、数据库

create database if not exists db_test engine=Memory
数据库也支持引擎
五中引擎

Ordinary:默认引擎

在这个数据库下可以使用任意类型的表引擎

DIctionary 字典引擎

适用于一次写入多次读取,小于百万级别的小表

Memory 内存引擎

存放在内存中,服务重启后数据消失

日志引擎

Mysql引擎

会自动拉取MySQL的数据,并为他们创建MySQL引擎的数据表

分区表

数据分区,数据的一种纵向切分,借助数据分区跳过不必要的数据目录,从而提升查询的性能,还能变相的实现数据的更新操作。数据分区支持删除、替换和重置,假设按着月份分区,数据就可以按月份的粒度进行替换更新。
目前只有合并树(mergeTree)家族才支持数据分区。

create table db_test2.partition_table
(
id Int64 comment ‘主键’,
table_schema String comment ‘库名’,
etl_time datetime comment ‘时间’
) engine=MergeTree() partition by toYYYYMM(etl_time) order by id ;
select table,partition,path from system.parts where table=‘partition_table’;
SELECT * FROM partition_v1 WHERE EventTime =‘2019-05-01’

在后续的查询过程中,可以利用分区索引跳过6月份分区目录。

查询分区信息

select table,partition,path from system.parts where table=‘partition_table’;

删除分区

alter table partition_table drop partition 20190501

删除分区后再重新写入,可以达到更新的目的

复制分区

两张表的表结构完全一致的情况并且都有分区键 可以复制分区

ALTER TABLE partition_v2 REPLACE PARTITION 201908 FROM partition_v1

数据写入

INSERT INTO partition_v2 VALUES (‘A0014’,toString(1+2), now())

INSERT INTO partition_v2 FORMAT CSV
‘A0017’,‘www.nauu.com’, ‘2019-10-01’
‘A0018’,‘www.nauu.com’, ‘2019-10-01’

数据删除

clickhouse有删除和修改的能力,但是不支持事务无法回滚,异步过程、很重的操作最好批量执行
删除

ALTER TABLE partition_v2 DELETE WHERE ID = ‘A003’

修改

ALTER TABLE partition_v2 DELETE WHERE ID = ‘A003’

视图

CREATE [MATERIALIZED] VIEW [IF NOT EXISTS] [db.]table_name [TO[db.]name] [ENGINE = engine] [POPULATE] AS SELECT

物化视图创建好之后,如果源表被写入新数据,那么物化视图也会同步更新。POPULATE修饰符决定了
物化视图的初始化策略:如果使用了POPULATE修饰符,那么在创建视图的过程中,会连带将源表中已存在
的数据一并导入,如同执行了SELECT INTO一般;反之,如果不使用POPULATE修饰符,那么物化视图在创
建之后是没有数据的,它只会同步在此之后被写入源表的数据。物化视图目前并不支持同步删除,如果在
源表中删除了数据,物化视图的数据仍会保留。

数据字典

数据会主动和被动加载到内存,并支持动态更新。字典数据常驻内存的特性,适合保存常亮和经常使用的维度表数据,避免不必要的join。

内部字典

不常用

外部扩展字典

载config.xml中会配置默认识别架子啊/et/clickhouse-server目录下所有_.dictionary.xml结尾的配置文件


*_dictionary.xml
完整的配置结构



dict_name














name

字典的名称,唯一标识,全局唯一

suructure

字典的数据结构



 -->



Id





...


数据结构是由键值key 和属性attribute组成,分别描述字典的数据标识和字段的属性。

键值key

数值型
使用ID配置 ,使用Uint64整数定义



Id

复合型使用tuple元组定义,类似数据库的复合主键



field1
String


field2
UInt64

省略…

attribute


Name
DataType


generateUUIDv4()
true
true
true

ClickHouse原理解析与应用实践_第5张图片

layout

字典的类型,决定了数据在内存中以什么结构组织和存储

flat

性能最高的字典类型,只能最多50万行数据。
完整的配置文件




test_flat_dict



/chbase/data/dictionaries /organization.csv
CSV








id


code
String



name
String




300
360



hashed

只能使用Uint64数值型key,但是没有上限




range_hashed

range_hashed字典可以看作hashed字典的变种,它在原有功能的基础上增加了指定时间区间的特性,数据会以散列结构存储并按照时排序。时间区间通过range_min和range_max元素指定,所指定的字段必须是Date或者DateTime类型。




test_range_hashed_dict


/chbase/data/dictionaries/sales.csv
CSV







id


start


end


price
Float32




300
360



查看字典

SELECT name, type, key, attribute.names, attribute.types FROM system.dictionaries

ClickHouse原理解析与应用实践_第6张图片

source

字典的数据源

文件类型

本地文件



/data/dictionaries/organization.csv
CSV


可执行文件



cat /data/dictionaries/organization.csv
CSV


远程文件



http://10.37.129.6/organization.csv
CSV


数据库类型

mysql



3306
root


10.37.129.2
1

test
t_organization
·port:数据库端口。 ·user:数据库用户名。 ·password:数据库密码。 ·replica:数据库host地址,支持MySQL集群。 ·db:database数据库。 ·table:字典对应的数据表。 ·where:查询table时的过滤条件,非必填项。 ·invalidate_query:指定一条SQL语句,用于在数据更新时判断是否需要更新

clickhouse



10.37.129.6
9000
default

default
t_organization
其中,各配置项的含义分别如下。 ·host:数据库host地址。 ·port:数据库端口。 ·user:数据库用户名。 ·password:数据库密码。 ·db:database数据库。 ·table:字典对应的数据表。 ·where:查询table时的过滤条件,非必填项。 ·invalidate_query:指定一条SQL语句,用于在数据更新时判断是否需要更新,非

mongoDB



test_mongodb_dict



10.37.129.2
27017


test
t_organization

 省略…
其中,各配置项的含义分别如下。
·host:数据库host地址。
·port:数据库端口。
·user:数据库用户名。
·password:数据库密码。
·db:database数据库。
·collection:与字典对应的collection的名

lifetime

字典的更新频率,秒

定时更新


300
360

当都等于时禁止字典更新

当达到指定秒后,数据字典会进行更新。

实时更新

对于文件类型会判断文件的修改时间,对于MySQL对根据

select updatetime from t_organization where id = 8

进行判断,如果两次的时间不一致,会进行全量更新。

MergeTree原理解析

在绝大多数的场景中都会用到这个表引擎。
高性能:列存储、自定义分区、稀疏的主索引

CREATE TABLE [IF NOT EXISTS] [db_name.]table_name (
name1 [type] [DEFAULT|MATERIALIZED|ALIAS expr],
name2 [type] [DEFAULT|MATERIALIZED|ALIAS expr],
省略...
) ENGINE = MergeTree()
[PARTITION BY expr]
[ORDER BY expr]
[PRIMARY KEY expr]
[SAMPLE BY expr]
[SETTINGS name=value, 省略...]

(1)PARTITION BY [选填]:分区键,用于指定表数据以何种标
准进行分区。分区键既可以是单个列字段,也可以通过元组的形式使
用多个列字段,同时它也支持使用列表达式。如果不声明分区键,则
ClickHouse会生成一个名为all的分区。合理使用数据分区,可以有效
减少查询时数据文件的扫描范围,更多关于数据分区的细节会在6.2节
介绍。
(2)ORDER BY [必填]:排序键,用于指定在一个数据片段内,
数据以何种标准排序。默认情况下主键(PRIMARY KEY)与排序键相
同。排序键既可以是单个列字段,例如ORDER BY CounterID,也可以
通过元组的形式使用多个列字段,例如ORDER
BY(CounterID,EventDate)。当使用多个列字段排序时,以ORDER
BY(CounterID,EventDate)为例,在单个数据片段内,数据首先会以
CounterID排序,相同CounterID的数据再按EventDate排序。
(3)PRIMARY KEY [选填]:主键,顾名思义,声明后会依照主键
字段生成一级索引,用于加速表查询。默认情况下,主键与排序键
(ORDER BY)相同,所以通常直接使用ORDER BY代为指定主键,无须刻
意通过PRIMARY KEY声明。所以在一般情况下,在单个数据片段内,数
据与一级索引以相同的规则升序排列。与其他数据库不同,MergeTree
主键允许存在重复数据(ReplacingMergeTree可以去重)。

数据分区

MergeTree数据分区规则是由分区键值决定的。四种规则
(1)不指定分区键:如果不使用分区键,即不使用PARTITION BY
声明任何分区表达式,则分区ID默认取名为all,所有的数据都会被写
入这个all分区。
(2)使用整型:如果分区键取值属于整型(兼容UInt64,包括有
符号整型和无符号整型),且无法转换为日期类型YYYYMMDD格式,则
直接按照该整型的字符形式输出,作为分区ID的取值。
(3)使用日期类型:如果分区键取值属于日期类型,或者是能够
转换为YYYYMMDD格式的整型,则使用按照YYYYMMDD进行格式化后的字
符形式输出,并作为分区ID的取值。
(4)使用其他类型:如果分区键取值既不属于整型,也不属于日
期类型,例如String、Float等,则通过128位Hash算法取其Hash值作
为分区ID的取值。

ClickHouse原理解析与应用实践_第7张图片

数据TTL

数据的存活时间

ReplacingMergeTree

一定程度上可以去除重复数据
创建方式

ENGINE = ReplacingMergeTree(ver)
强制触发合并
optimize TABLE replace_table FINAL

(1)使用ORBER BY排序键作为判断重复数据的唯一键。
(2)只有在合并分区的时候才会触发删除重复数据的逻辑。
(3)以数据分区为单位删除重复数据。当分区合并时,同一分区
内的重复数据会被删除;不同分区之间的重复数据不会被删除。
(4)在进行数据去重时,因为分区内的数据已经基于ORBER BY进
行了排序,所以能够找到那些相邻的重复数据。
(5)版本号里面可以配置字段会根据字段保留最大值一条;不填是保留最后一条。

summingMergeTree

ENGINE = SummingMergeTree((col1,col2,…))

适用需求:只需要查询数据的汇总结果,不关心明细数据。
(1)用ORBER BY排序键作为聚合数据的条件Key。
(2)只有在合并分区的时候才会触发汇总的逻辑。
(3)以数据分区为单位来聚合数据。当分区合并时,同一数据分
区内聚合Key相同的数据会被合并汇总,而不同分区之间的数据则不会
被汇总。
(4)如果在定义引擎时指定了columns汇总列(非主键的数值类型
字段),则SUM汇总这些列字段;如果未指定,则聚合所有非主键的数
值类型字段。
(5)在进行数据汇总时,因为分区内的数据已经基于ORBER BY排
序,所以能够找到相邻且拥有相同聚合Key的数据。
(6)在汇总数据时,同一分区内,相同聚合Key的多行数据会合并
成一行。其中,汇总字段会进行SUM计算;对于那些非汇总字段,则会
使用第一行数据的取值。

AggregatingMergeTree

数据立方体的概念,是SummingMergeTree的升级版,可以自定义聚合方式。
通常搭配MergeTree底表搭配使用
先创建底表

CREATE TABLE agg_table_basic(
id String,
city String,
code String,
value UInt32
)ENGINE = MergeTree()
PARTITION BY city
ORDER BY (id,city)
然后创建固化视图
CREATE MATERIALIZED VIEW agg_view
ENGINE = AggregatingMergeTree()
PARTITION BY city
ORDER BY (id,city)
AS SELECT
id,
city,
uniqState(code) AS code,
sumState(value) AS value
FROM agg_table_basic
GROUP BY id, city
新增数据到底表
INSERT INTO TABLE agg_table_basic
VALUES('A000','wuhan','code1',100),('A000','wuhan','code2',200),('A000','zhuhai', 'code1',200)
数据会自动的同步到物化视图,并按照aggregatingMErgeTree引擎进行规则处理
查询数据
SELECT id, sumMerge(value), uniqMerge(code) FROM agg_view GROUP BY id, city

(1)用ORBER BY排序键作为聚合数据的条件Key。
(2)使用AggregateFunction字段类型定义聚合函数的类型以及聚合的字段。
(3)只有在合并分区的时候才会触发聚合计算的逻辑。
(4)以数据分区为单位来聚合数据。当分区合并时,同一数据分区内聚合Key相同的数据会被合并计算,而不同分区之间的数据则不会被计算。
(5)在进行数据计算时,因为分区内的数据已经基于ORBER BY排序,所以能够找到那些相邻且拥有相同聚合Key的数据。
(6)在聚合数据时,同一分区内,相同聚合Key的多行数据会合并成一行。对于那些非主键、非AggregateFunction类型字段,则会使用第一行数据的取值。
(7)AggregateFunction类型的字段使用二进制存储,在写入数据时,需要调用State函数;而在查询数据时,则需要调用相应的Merge函数。其中,*表示定义时使用的聚合函数。
(8)AggregatingMergeTree通常作为物化视图的表引擎,与普通MergeTree搭配使用

CollapsingMergeTree

支持增删的引擎,通过以增代删的思路进行行级别的修改和删除。定义一个sign标记位字段,如果数据航的状态是1标识是一条有效的数据;如果sign标记行是-1,标识数据需要被删除。
通过order by -1 和1 进行两两抵消,如果-1=1数量 ,这条数据消失。如果1>-1数量,修改操作保留1数据。
有个致命缺点是顺序不能乱,不能先-1在1

CREATE TABLE collpase_table(
id String,
code Int32,
create_time DateTime,
sign Int8
)ENGINE = CollapsingMergeTree(sign)
PARTITION BY toYYYYMM(create_time)
ORDER BY id

VersionedCollapsingMergeTree

创建方式

CREATE TABLE ver_collpase_table(
id String,
code Int32,
create_time DateTime,
sign Int8,
ver UInt8
)ENGINE = VersionedCollapsingMergeTree(sign,ver)
PARTITION BY toYYYYMM(create_time)
ORDER BY id

加入版本的控制,不在局限于写入的顺序

其他表引擎

外部存储类型

只负责元数据管理和数据查询,数据文件由外部系统提供

hdfs

创建方式

CREATE TABLE hdfs_table1(
id UInt32,
code String,
name String
)ENGINE = HDFS(‘hdfs://hdp1.nauu.com:8020/clickhouse/hdfs_table1’,‘CSV’)

format表示文件格式(指ClickHouse支持的文件格式,常见的有CSV、TSV
和JSON等)。
数据写入到clickhouse中后,同时会将数据以CSV的格式写到HDFS上,但是不支持是删除HDFS上文件。

MySQL
ENGINE = MySQL('host:port', 'database', 'table', 'user', 'password'[, replace_query, 'on_duplicate_clause'])
其中各参数的含义分别如下:
·host:port表示MySQL的地址和端口。
·database表示数据库的名称。
·table表示需要映射的表名称。
·user表示MySQL的用户名。
·password表示MySQL的密码。
·replace_query默认为0,对应MySQL的REPLACE INTO语法。如果将它设置为1,则会用REPLACE
INTO代替INSERT INTO。
·on_duplicate_clause默认为0,对应MySQL的ON DUPLICATE KEY语法。如果需要使用该设置,
则必须将replace_query设置成0。

总结

提示:这里 对文章进行总结:

例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

你可能感兴趣的:(clickHouse,clickhouse,大数据,hadoop)