1、介绍
ClickHouse是俄罗斯的Yandex于2016年开源的列式存储数据库(DBMS),使用C++语言编写,主要用于在线分析处理查询(OLAP),能够使用SQL查询实时生成分析数据报告。
OLAP(On-Line Analytical Processing)翻译为联机分析处理,专注于分析处理,从对数据库操作来看,OLAP是对数据的查询;
OLTP(on-line transaction processing)翻译为联机事务处理,专注于事务处理,从对数据库操作来看,OLTP主要是对数据的增删改。
1.1、特点:列式存储
以下面的表为例:
1)采用行式存储时,数据在磁盘上的组织结构为:
好处是想查某个人所有的属性时,可以通过一次磁盘查找加顺序读取就可以。但是当想查所有人的年龄时,需要不停的查找,或者全表扫描才行,遍历的很多数据都是不需要的。
2)采用列式存储时,数据在磁盘上的组织结构为:
这时想查所有人的年龄只需把年龄那一列拿出来就可以了。
3)列式存储的好处:
对于列的聚合、计数、求和等统计操作原因优于行式存储;
由于某一列的数据类型都是相同的,针对于数据存储更容易进行数据压缩,每一列选择更优的数据压缩算法,大大提高了数据的压缩比重;
由于数据压缩比更好,一方面节省了磁盘空间,另一方面对于cache也有了更大的发挥空间
DBMS的功能:几乎覆盖了标准SQL的大部分语法,包括DDL和DML,以及配套的各种函数,用户管理及权限管理,数据的备份与恢复;
1.2、多样化引擎
ClickHouse和MySQL类似,把表级的存储引擎插件化,根据表的不同需求可以设定不同的存储引擎。目前包括合并树、日志、接口和其他四大类20多种引擎;
1.3、高吞吐写入能力
ClickHouse采用类LSM Tree的结构,数据写入后定期在后台Compaction。通过类LSM tree的结构,ClickHouse在数据导入时全部是顺序append写,写入后数据段不可更改,在后台compaction时也是多个段merge sort后顺序写回磁盘。顺序写的特性,充分利用了磁盘的吞吐能力,即便在HDD上也有着优异的写入性能。
官方公开benchmark测试显示能够达到50MB-200MB/s的写入吞吐能力,按照每行100Byte估算,大约相当于50W-200W条/s的写入速度
1.4、数据分区与线程级并行
ClickHouse将数据划分为多个partition,每个partition再进一步划分为多个index granularity(索引粒度),然后通过多个CPU核心分别处理其中的一部分来实现并行数据处理。在这种设计下,单条Query就能利用整机所有CPU。极致的并行处理能力,极大的降低了查询延时
所以,ClickHouse即使对于大量数据的查询也能够化整为零平行处理。但是有一个弊端就是对于单条查询使用多cpu,就不利于同时并发多条查询。所以对于高qps的查询业务,ClickHouse并不是强项
2、安装
2.1、准备工作
确定防火墙处于关闭状态
CentOS取消打开文件数限制
sudo vim /etc/security/limits.conf
在末尾加入:
* soft nofile 65536
* hard nofile 65536
* soft nproc 131072
* hard nproc 131072
第一列是限制的用户和用户组,soft软限制,hard硬限制,nofile打开文件数,nproc用户进程数,退出当前用户,重启登录,ulimit -a
查看打开文件数和用户进程数是否更改
[root@aliyun ~]# ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 7284
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 65536
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 131072
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
2.2、安装依赖
sudo yum install -y libtool
sudo yum install -y *unixODBC*
CentOS取消SELINUX(不知道为什么我修改后,就没网了) vim /etc/selinux/config 修改为:SELINUX=disabled 修改完重启服务器
单机安装,下载安装包,安装包下载,需要以下四个rpm包:
clickhouse-client-21.7.3.14-2.noarch.rpm
clickhouse-common-static-21.7.3.14-2.x86_64.rpm
clickhouse-common-static-dbg-21.7.3.14-2.x86_64.rpm
clickhouse-server-21.7.3.14-2.noarch.rpm
mac下要下载arm的,注意!!!
wget https://repo.yandex.ru/clickhouse/rpm/stable/x86_64/clickhouse-client-21.7.3.14-2.noarch.rpm
wget https://repo.yandex.ru/clickhouse/rpm/stable/x86_64/clickhouse-common-static-21.7.3.14-2.x86_64.rpm
wget https://repo.yandex.ru/clickhouse/rpm/stable/x86_64/clickhouse-common-static-dbg-21.7.3.14-2.x86_64.rpm
wget https://repo.yandex.ru/clickhouse/rpm/stable/x86_64/clickhouse-server-21.7.3.14-2.noarch.rpm
2.3、修改配置文件
cd /etc/clickhouse-server/
sudo chmod 777 config.xml
sudo vim config.xml
把<listen_host>0.0.0.0</listen_host>的注释打开,这样的话才能让ClickHouse被除本机之外的服务器访问。
这个配置文件中,ClickHouse一些默认路径配置:
数据文件路径:<path>/var/lib/clickhouse/</path>
日志文件路径:<log>/var/log/clickhouse-server/clickhouse-server.log</log>
启动Server
sudo systemctl start clickhouse-server
或者
sudo clickhouse start
查看启动状态:
sudo systemctl status clickhouse-server
或者
sudo clickhouse status
关闭开启自启
sudo systemctl disable clickhouse-server
2.4、使用client连接server
clickhouse-client -m
在连接的过程中出现了两个错误:错误一:
Code: 210. DB::NetException: Connection
refused (localhost:9000). (NETWORK_ERROR)
如果在配置文件中有<listen_host>::</listen_host>,就改成<listen_host>0.0.0.0</listen_host>,因为::是IPv6的通配符,我部署clickhouse的机器不支持ipv6。
错误二:
Code: 516. DB::Exception: Received from localhost:9000. DB::Exception: default: Authentication failed: password is incorrect or there is no user with such name. (AUTHENTICATION_FAILED)
在命令中带上--password:clickhouse-client -m --password
3、数据类型
3.1、整形
固定长度的整型,包括有符号整型或无符号整型:Int8、Int16、Int32、Int64
3.2、浮点数
Float32、Float64
浮点数计算精度缺失问题:select 1.0-0.9
┌──────minus(1., 0.9)─┐
│ 0.09999999999999998 │
└─────────────────────┘
3.3、布尔型
没有单独的类型来存储布尔值。可以使用UInt8类型,取值限制为0或1。
Decimal型
Decimal32(s)相当于Decimal(9-s,s)
Decimal64(s)相当于Decimal(18-s,s)
Decimal128(s)相当于Decimal(38-s,s)
3.4、字符串
String:字符串可以任意长度的。它可以包含任意的字节集,包含空字节;
FixedString(N):固定长度N的字符串,N必须是严格的正自然数。当服务端读取长度小于N的字符串时候,通过在字符串末尾添加空字节来达到N字节长度。当服务端读取长度大于N的字符串时候,将返回错误消息。
3.5、枚举类型
包括Enum8和Enum16类型。Enum保存**’string’=integer**的对应关系
Enum8用’string’=Int8来描述
Enum16用’string’=Int16来描述
创建一个带有一个枚举Enum8(‘hello’ = 1, ‘world’ = 2)类型的列:
create table t_enum(
x Enum8('hello' = 1,'world' = 2)
)engine = TinyLog;
这个x列只能存储类型定义中列出的值:‘hello’或’world’:
inser tinto t_enum values ('hello'),('hello'),('world'),('world');
如果尝试保存任何其他值,ClickHouse抛出异常:
insert into t_enum values('a');
如果需要看到对应行的数值,则必须将Enum值转换为整数类型:
select cast(x,'Int8') from t_enum;
3.6、时间类型
目前ClickHouse有三种时间类型:
Date接受年-月-日的字符串,比如:2019-12-16;
Datetime接受年-月-日 时:分:秒的字符串,比如2019-12-16 20:50:10;
Datetime64 接受年-月-日 时:分:秒.亚秒的字符串,比如2019-12-16 20:50:10.66。
日期类型用两个字节存储,表示从1970-01-01到当前的日期值
3.7、数组
Array(T):由T类型元素组成的数组,T可以是任意类型,包含数组类型。但不推荐使用多维数组,ClickHouse对多维数组的支持有限。例如,不能在MergeTree表中存储多维数组,创建数组方式:使用array函数
select array(1, 2) as x, toTypeName(x);
使用方括号
select [1, 2] as x, toTypeName(x);
4、SQL操作
Insert
基本与标准SQL(MySQL)基本一致:
标准:
insert into [table_name] values(…),(…)
从表中插入表:
insert into [table_name] select a,b,c from [table_name_2]
Update和Delete
ClickHouse提供了Delete和Update的能力,这类操作被称为Mutation查询,它可以看做Alter的一种。虽然可以实现修改和删除,但是和一般的OLTP数据库不一样,Mutation语句是一种很重的操作,而且不支持事务。
重的原因主要是每次修改或者删除都会导致放弃目标数据的原有分区,重建新分区,所以尽量做批量的变更,不要进行频繁小数据的操作。
删除操作:
alter table t_order_smt delete where sku_id ='sku_001';
修改操作:
alter table t_order_smt update total_amount=toDecimal32(2000.00,2)
where id=102;
由于操作比较重,所以Mutation语句分两步执行,同步执行的部分其实只是进行新增数据、新增分区和并把旧分区打上逻辑上的失效标记。直到触发分区合并的时候,才会删除旧数据释放磁盘空间,一般不会开放这样的功能给用户,由管理员完成。
查询操作
ClickHouse基本上与标准SQL差别不大:
支持子查询;
支持CTE(Common Table Expression公用表表达式with子句);
支持各种JOIN,但是JOIN操作无法使用缓存,所以即使是两次相同的JOIN语句,ClickHouse也会视为两条新SQL;
不支持自定义函数;
GROUP BY操作增加了with rollup、with cube、with total用来计算小计和总计。
测试下GROUP BY的三种操作,看下数据:
┌──id─┬─sku_id──┬─total_amount─┬─────────create_time─┐
│ 101 │ sku_001 │ 1000 │ 2020-06-01 12:00:00 │
│ 101 │ sku_001 │ 1000 │ 2020-06-01 12:00:00 │
│ 102 │ sku_002 │ 2000 │ 2020-06-01 11:00:00 │
│ 102 │ sku_002 │ 2000 │ 2020-06-01 13:00:00 │
│ 102 │ sku_002 │ 12000 │ 2020-06-01 13:00:00 │
│ 102 │ sku_002 │ 2000 │ 2020-06-01 11:00:00 │
│ 102 │ sku_002 │ 2000 │ 2020-06-01 13:00:00 │
│ 102 │ sku_002 │ 12000 │ 2020-06-01 13:00:00 │
│ 102 │ sku_004 │ 2500 │ 2020-06-01 12:00:00 │
│ 102 │ sku_004 │ 2500 │ 2020-06-01 12:00:00 │
└─────┴─────────┴──────────────┴─────────────────────┘
┌──id─┬─sku_id──┬─total_amount─┬─────────create_time─┐
│ 102 │ sku_002 │ 600 │ 2020-06-02 12:00:00 │
│ 102 │ sku_002 │ 600 │ 2020-06-02 12:00:00 │
└─────┴─────────┴──────────────┴─────────────────────┘
with rollup:从右至左去掉维度进行小计
select id,sku_id,sum(total_amount) from t_order_mt
group by id,sku_id with rollup;
with cube : 从右至左去掉维度进行小计,再从左至右去掉维度进行小计
select id,sku_id,sum(total_amount) from t_order_mt
group by id,sku_id with cube;
with totals: 只计算合计
select id,sku_id,sum(total_amount) from t_order_mt
group by id,sku_id with totals;
alter操作,同MySQL的修改字段基本一致。
1)新增字段:alter table tableName add column newcolname String after col1;
2)修改字段类型:alter table tableName modify column newcolname String;
3)删除字段:alter table tableName drop column newcolname;
导出数据
clickhouse-client --query "select * from
t_order_mt where create_time='2022-08-28 12:00:00'"
--format CSVWithNames> /opt/module/data/rs1.csv