ClickHouse原理及使用

2022-04-06 00:00:00 数据 数组 类型 嵌套 数据类型

一、ClickHouse 概述
1.1 什么是ClickHouse
ClickHouse 是俄罗斯的 Yandex 于2016年开源的列式存储数据库(DBMS),主要用于在线分析处理查询(OLAP),能够使用SQL 查询实时生成分析数据报告。

1.2 什么是列式存储
以下面的表为例:

Id Name Age
1 张三 18
2 李四 22
3 王五 34
采用行式存储时,数据在磁盘上的组织结构为:



好处是想查某个人所有的属性时,可以通过一次磁盘查找加顺序读取就可以。但是当想查所有人的年龄时,需要不停的查找,或者全表扫描才行,遍历的很多数据都是不需要的。

而采用列式存储时,数据在磁盘上的组织结构为:



这时想查所有人的年龄只需把年龄那一列拿出来就可以了。

1.3 安装前的准备
1.3.1 CentOS 取消打开文件数限制
在/etc/security/limits.conf、 /etc/security/limits.d/90-nproc.conf 这2个文件的末尾加入一下内容:

vi /etc/security/limits.conf
在文件末尾添加:
* soft nofile 65536
* hard nofile 65536
* soft nproc 131072
* hard nproc 131072

vi /etc/security/limits.d/90-nproc.conf
在文件末尾添加:
* soft nofile 65536
* hard nofile 65536
* soft nproc 131072
* hard nproc 131072
重启服务器之后生效,用ulimit -n 或者 ulimit -a 查看设置结果

ulimit -n
1.3.2 CentOS 取消SELINUX
SELINUX 是 CentOS 类似于windows 下的安全360

修改 /etc/selinux/config 中的 SELINUX=disabled 后重启

vi /etc/selinux/config
SELINUX=disabled
1.3.3 关闭防火墙
service iptables stop
service ip6tables stop
1.3.4 安装依赖
yum install -y libtool
yum install -y *unixODBC*
yum search libicu
yum install libicu.x86_64
二、安装
2.1 网址
官网:https://clickhouse.yandex/

下载地址:http://repo.red-soft.biz/repos/clickhouse/stable/el7/

2.2 单机模式
2.2.1 上传5个文件到 mkdir /usr/local/clickhouse
clickhouse-client-1.1.54236-4.el7.x86_64.rpm 09-Jun-2017 11:02 3.0K
clickhouse-compressor-1.1.54236-4.el7.x86_64.rpm 09-Jun-2017 11:02 880K
clickhouse-debuginfo-1.1.54236-4.el7.x86_64.rpm 09-Jun-2017 11:02 8.6M
clickhouse-server-1.1.54236-4.el7.x86_64.rpm 09-Jun-2017 11:02 32M
clickhouse-server-common-1.1.54236-4.el7.x86_64.rpm 09-Jun-2017 11:02 8.0K
2.2.2 分别安装这5个rpm 文件
rpm -ivh /usr/local/clickhouse/*.rpm
2.2.3 启动 ClickServer
前台启动:

clickhouse-server --config-file=/etc/clickhouse-server/config.xml
查看启动后的进程:ps -aux | grep click

后台启动:

nohup clickhouse-server --config-file=/etc/clickhouse-server/config.xml >null 2>&1 &
2.2.4 使用 client 连接server
clickhouse-client
2.3 分布式集群安装
2.3.1 在node-02、node-03 上面执行之前的所有步骤
2.3.2 三台机器修改配置文件 vi /etc/clickhouse-server/config.xml
<listen_host>0.0.0.0</listen_host>
<!-- <listen_host>::1</listen_host> -->
<!-- <listen_host>127.0.0.1</listen_host> -->
将刚刚修改好的配置分发到三台机器上去: ync.sh /etc/clickhouse-server/config.xml

2.3.3 在三台机器的etc 目录下新建 metrika.xml 文件
vi /etc/metrika.xml
添加如下内容:

<yandex>
<clickhouse_remote_servers>
<perftest_3shards_1replicas>
<shard>
<internal_replication>true</internal_replication>
<replica>
<host>node-01</host>
<port>9000</port>
</replica>
</shard>
<shard>
<replica>
<internal_replication>true</internal_replication>
<host>node-02</host>
<port>9000</port>
</replica>
</shard>
<shard>
<internal_replication>true</internal_replication>
<replica>
<host>node-03</host>
<port>9000</port>
</replica>
</shard>
</perftest_3shards_1replicas>
</clickhouse_remote_servers>

<!--zookeeper相关配置-->
<zookeeper-servers>
<node index="1">
<host>node-01</host>
<port>2181</port>
</node>
<node index="2">
<host>node-02</host>
<port>2181</port>
</node>
<node index="3">
<host>node-03</host>
<port>2181</port>
</node>
</zookeeper-servers>

<macros>
<replica>node-01</replica>
</macros>

<networks>
<ip>::/0</ip>
</networks>

<clickhouse_compression>
<case>
<min_part_size>10000000000</min_part_size>
<min_part_size_ratio>0.01</min_part_size_ratio>
<method>lz4</method>
</case>
</clickhouse_compression>

</yandex>
注意:下面标红的地方需要根据机器不同去修改,node-02就是修改成node-02, node-03就是修改成node-03

<macros>
<replica>node-01</replica>
</macros>

3.3.4 三台机器启 ClickServer
首先在三台机器开启Zookeeper

前台启动:

clickhouse-server --config-file=/etc/clickhouse-server/config.xml
查看启动后的进程:ps -aux | grep click

后台启动:

nohup clickhouse-server --config-file=/etc/clickhouse-server/config.xml >null 2>&1 &
集群搭建成功,进入clickhouse-client 客户端:



三、数据类型
3.1 整型
固定长度的整型,包括有符号整型或无符号整型。Clickhouse 对大小写敏感。

整型范围(-2^(n-1) ~ 2^(n-1) - 1):

Int8 [-128 : 127]
Int16 [-32768 : 32767]
Int32 [-2147483648 : 2147483647]
Int64 [-9223372036854775808 : 9223372036854775807]
无符号整型范围(0 ~ 2^n -1)

UInt8 [0 : 255]
UInt16 [0 : 65535]
UInt32 [0 : 4294967295]
UInt64 [0 : 18446744073709551615]
3.2 浮点型
Float32 - float
Float64 - double
建议尽可能以整型形式存储数据。例如,将固定精度的数字转换为整数值,如果间用毫秒为单位表示,因为浮点型进行计算时可能引起四舍五入的误差。



与标准SQL 相比,ClickHouse 支持以下类别的浮点数:

Inf - 正无穷



-Inf - 负无穷



NaN - 非数字:



3.3 布尔型
没有单独的类型来存储布尔值。可以使用 UInt8 类型,取值限制为 0 或 1 。

3.4 字符串
1)String

字符串可以任意长度的。它可以包含任意的字节集,包含空字节。

2) FixedString(N)

固定长度N 的字符串,N 必须是严格的正自然数。当服务端读取长度小于N的字符串时候,通过在字符串末尾添加空字节来达到N 字节长度。当服务端读取长度大于 N 的字符串时候,将返回错误消息。

与String 相比,极少会使用FixedString,因为使用起来不是很方便。

3.5 枚举类型
ClickHouse 支持枚举类型,这是一种在定义常量时经常会使用的数据类型。ClickHouse 提供了Enum8 和Enum16 两种枚举类型,它们除了取值范围不同之外,别无二致。枚举固定使用(String:Int)Key/Value 键值对的形式定义数据,所以Enum8 和Enum16分别会对应(String:Int8)和(String:Int16)!



包括 Enum8 和 Enum16 类型。Enum 保存 'string' = integer 的对应关系。

Enum8 用 'String'=Int8 对描述。

Enum16 用 'String'=Int16 对描述。

用法演示:

创建一个带有一个枚举 Enum8('hello'=1,'world'=2) 类型的列:

create table enum(enum Enum8('hello'=0, 'enum'=1))engine=TinyLog






示例2:

-- 枚举数据类型
CREATE TABLE test_enum(id Int8, color Enum8('red'=1, 'green'=2, 'blue'=3)) engine=Memory;
insert into test_enum values(1,'red'),(2,'red'),(3,'green');
-- 也可以使用这种方式进行插入数据:
insert into test_enum values(4,3);
insert into test_enum values(5,'pink'); -- 没有声明的值是不能插入

select id, toInt32(color) from test_enum;
-- 节省存储空间,提升处理效率;底层存储Int类型,占用空间小
3.6 数组
Array(T):由T 类型元素组成的数组。

T 可以是任意类型,包含数组类型。但不推荐使用多维数组,ClickHouse 对多维数组的支持有限。例如,不能在MergeTree 表中存储多维数组。

可以使用 array 函数来创建数组:array(T)

也可以使用方括号:[]

-- 数组数据类型

array(T) 数组是强数据类型

[e1,e2,d3...]

toTypeName() -- 查看变量的数据类型

创建数组案例:



示例:

select array(1,2,3,4);




案例2:

CREATE TABLE test_array
(
name String,
hobby Array(String)
) ENGINE = Log

insert into test_array values
('张三',['读书','爬山','散步']),
('李四',['read','hiking','dance']),
('王五',array('吃','睡','喝','玩'));

select * from test_array;

insert into test_array values ('张三2',['读书','爬山','散步']);
insert into test_array values ('李四2',['read','hiking','dance']);
insert into test_array values ('王五2',array('吃','睡','喝','玩'));

-- clickhouse 会利用多核处理器将数据分块存储、计算
select * from test_array;

-- 查询数组中的数据
select *, hobby[1] from test_array;

-- 遍历数组中每个元素,给每个元素加上'abc'
select arrayMap(e -> concat(e, 'abc'), hobby) from test_array;
3.7 Tupe 元组
是一个特殊的数据类型,集合
可以存储任意的数据类型,在定义的时候声明数据类型和数据元素个数
元组类型由1~n 个元素组成,每个元素之间允许设置不同的数据类型,且彼此之间不要求兼容。无组同样支持类型推断,
其推断依据仍然以小存储代码为原则。与数组类似,元组也可以使用两种方式定义

常规方式tuple(T):元组中可以存储多种数据类型,但是要注意数据类型的顺序
Tuple(String, UInt8, Date)

select tuple(1, 'abc', 12.33) as x, toTypeName(x);

┌─x───────────────┬─toTypeName(tuple(1, \'abc\', 12.33))─┐
│ (1,'abc',12.33) │ Tuple(UInt8, String, Float64) │
└─────────────────┴──────────────────────────────────────┘

select (1, 2, 'hello') as x, toTypeName(x);
┌─x─────────────┬─toTypeName(tuple(1, 2, \'hello\'))─┐
│ (1,2,'hello') │ Tuple(UInt8, UInt8, String) │
└───────────────┴────────────────────────────────────┘
创建tuple表及查询示例:

-- 注意:建表的时候使用元组的需要制定元组的数据类型
create table test_tuple(
name String,
info Tuple(String, String, UInt8)
) engine=Memory;

insert into test_tuple values
('zss', ('M', 'coder', 23)),
('lss', tuple('F', 'coder', 23));

select * from test_tuple;

┌─name─┬─info─────────────┐
│ zss │ ('M','coder',23) │
│ lss │ ('F','coder',23) │
└──────┴──────────────────┘

-- 通过下标查询tupe数据
select name, info.1, info.2, info.3 from test_tuple;

┌─name─┬─tupleElement(info, 1)─┬─tupleElement(info, 2)─┬─tupleElement(info, 3)─┐
│ zss │ M │ coder │ 23 │
│ lss │ F │ coder │ 23 │
└──────┴───────────────────────┴───────────────────────┴───────────────────────┘
3.8 Nested 嵌套表结构
Nested 是一种嵌套表结构。一张数据表,可以定义任意多个嵌套类型字段,但每个字段的嵌套层级只支持一级,
即嵌套表内不能继续使用嵌套类型。对于简单场景的层级关系或关联关系,使用嵌套类型也是一种不错的选择。

create table test_nested (
id Int8,
name String,
hobby Nested(
hid Int8,
h1 String,
h2 String
)
)engine=Memory;

查看表结构:
┌─name──────┬─type──────────┬─default_type─┬─default_expression─┐
│ id │ Int8 │ │ │
│ name │ String │ │ │
│ hobby.hid │ Array(Int8) │ │ │
│ hobby.h1 │ Array(String) │ │ │
│ hobby.h2 │ Array(String) │ │ │
└───────────┴───────────────┴──────────────┴────────────────────┘

嵌套类型本质是一种多维数组的结构。嵌套表中每个字段都是一个数组,并且行与行之间数组的长度无须对齐。
需要注意的是,在同一行数据内每个数组字段的长度必须相等。

-- 插入数据
insert into test_nested values (1, 'zss', [1,2,3],['吃','喝','睡'],['eat','drink','sleep']);
insert into test_nested values (2, 'lss', [1,2,3],['吃','喝','睡'],['eat','drink','sleep']);

-- 查询数据
select * from test_nested;

┌─id─┬─name─┬─hobby.hid─┬─hobby.h1──────┬─hobby.h2────────────────┐
│ 1 │ zss │ [1,2,3] │ ['吃','喝','睡'] │ ['eat','drink','sleep'] │
└────┴──────┴───────────┴───────────────┴─────────────────────────┘
┌─id─┬─name─┬─hobby.hid─┬─hobby.h1──────┬─hobby.h2────────────────┐
│ 2 │ lss │ [1,2,3] │ ['吃','喝','睡'] │ ['eat','drink','sleep'] │
└────┴──────┴───────────┴───────────────┴─────────────────────────┘

-- 复杂查询数据
select id, name, hobby.hid, hobby.h1, hobby.h1[1] from test_nested;

┌─id─┬─name─┬─hobby.hid─┬─hobby.h1──────┬─arrayElement(hobby.h1, 1)─┐
│ 1 │ zss │ [1,2,3] │ ['吃','喝','睡'] │ 吃 │
└────┴──────┴───────────┴───────────────┴───────────────────────────┘
┌─id─┬─name─┬─hobby.hid─┬─hobby.h1──────┬─arrayElement(hobby.h1, 1)─┐
│ 2 │ lss │ [1,2,3] │ ['吃','喝','睡'] │ 吃 │
└────┴──────┴───────────┴───────────────┴───────────────────────────┘
3.9 复杂数据类型
3.9.1 domain
-- Domain pojo beans:https://clickhouse.tech/docs/zh/sql-reference/;

-- 再次插入数据,进入到/var/lib/clickhouse/data/test_db/tb_partition/ 会发现11、12月份的数据都各有2个块
insert into tb_partition values
(4, '2020-12-01 11:00:21', 100),
(5, '2020-12-02 11:12:21', 300),
(6, '2020-11-01 11:00:21', 200);

-- 合并数据
optimize table tb_partition; -- 一次合并两个分区

-- 进入到/var/lib/clickhouse/data/test_db/tb_partition/ 会发现11、12月份的数据都各有1个块
-- 之前老的分区,默认8分钟会被删除
六、DDL
————————————————
版权声明:本文为CSDN博主「不埋雷的探长」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_32265569/article/details/111822811

相关文章