DB-ClickHouse-01

1.1什么是ClickHouse

ClickHouse是俄罗斯的Yandex于2016年开源的列式存储数据库(DBMS),主要用于在线分析处理查询(OLAP),能够使用SQL查询实时生成分析数据报告,C++语言编写的

OLAP

定位就是用于OLAP离线数据处理,相比较于OLTP在线事务处理,CK更关注于对海量数据的计算分析,关注的是数据吞吐、查询速度、计算机性能等指标。而对于数据频繁的修改变更,则不太擅长,所以CK通常用来构建后端的实时数仓或者离线速仓

1.2什么是列式存储

CK是真正意义上的列式存储数据库,传统数据库存储数据是按照数据行进行存储

行式存储:数据完整性

列式存储:相较于行式存储很多数据计算方面会体现很多优势

例如:通常一个计算过程都只会用到少数几个列的数据,这时行式存储就需要读取到相关行所有列数据在进行过滤,而列式存储就可以直接读取到这几个列的相关数据,而不用查找其他不关心的数据

适用场景:

一个典型的OLAP场景主要是对海量数据进行更新,相比较于常用的mysql等OLTP数据库有一些明显的特征

  • 绝大多数请求都是读请求,对数据的修改比较少或者几乎没有
  • 数据量很大,这个量既包括数据的行数,也包括数据的列数、也就是通常说的宽表。大部分情况下对分布式表结构的要求是必须的
  • 数据通常以大的批次进行整体更新,而不是单行更新。这需要有很高的数据吞吐量。
  • 对事物的要求不是必须的。对于数据一致性的要求不会太高。通常只要求数据最终一致性

CK的数据吞吐量相当大,能够存储海量的数据,并能够以水平扩展的方式进行扩容,对大表的查询计算处理效率也非常高。甚至很多场景下都可以拥有媲美于关系型数据库的查询效率。官网给出的一些测试数据也大都是上千万行*数百列的数据规模。很多大规模的数据查询也都能轻松达到毫米级别。

但是需要指出,CK高性能的背后伴随计算机资源的大量消耗,CK对内存和CPU的占用都非常高,一个很普遍的查询都可能需要消耗非常多的资源,因此CK的查询频率也不宜太高,过于频繁的连续或者并发查询甚至很容易导致服务直接崩溃

综合评价CK的特点,非常适合用于后端数仓的建设。当然,这本身也是CK的设计目标

1.3安装前的准备工作

CK官网clickhouse.com

1.3.1CentOS取消打开文件限制

/etc/security//limits.conf /etc/security/limits.d/90/nproc.cnf这两个文件末尾加入以下内容

vim /etc/security//limits.conf
*soft noflie 65536
*hard nofile 65536
*soft nproc 131072
*hard nproc 131072

vim /etc/security/limits.d/90/nproc.cnf
*soft noflie 65536
*hard nofile 65536
*soft nproc 131072
*hard nproc 131072

重启服务器之后生效 ,用ulimit -n或者ulimit -a查询设置结果

1.3.2取消SELINUX

修改/etc/selinux/config中的SELINUX=disabled(/etc/sysconfig/selinux)

vim /etc/selinux/config
SELINUX=disabled

1.3.3关闭防火墙

1.3.4安装依赖

yum install -y libtool
yum install -y *unixODBC*

安装

官网:https://clickhouse.yandex

下载地址:https://packagecloud.io/altinity/clickhouse

https://packages.clickhouse.com/tgz/

下载安装包到本地之后执行install下的doinstall脚本

连接路径:/etc/usr

日志路径:/var/log/clickhouse

server配置文件:/etc/clickhouse-server/

client配置文件:/etc/clickhouse-client/

数据文件目录:/var/lib/clickhouse/

metadata:元数据

data:数据

使用-连接

修改配置:能远程连接

http请求 ip+8123/?query=show databases

  1. 使用驱动包导入官方的启动或者第三方驱动
  2. CK完全兼容了mysql和postgresql两个数据库,可以对应用他们的驱动直接连接,mysql服务默认端口9004,postgresql端口9005

库引擎

建库

使用数据库首先要建库,CK提供多种库引擎实现不同场景下的库声明

Atomic库引擎

这是CK默认的库引擎,默认创建的default库就是使用这种引擎,可以在监控是进行声明

create database test engine = atomic;

Atomic类型的数据库完全有CK自己管理数据。每个数据库对应/var/lib/data目录下的一个子目录。数据库中的表会分配一个唯一的UUID,数据存储的目录/var/lib.clickhouse/store/xxx/xxxxx 最后这个是该表的uuid

Mysql引擎

数据类型

CK的极简化设计在基础数据类型中体现的尤为明显

整型

CK中的整型不香其他数据库中区分int、short、long等等在这些类型,而是统一表示固定长度的整数,包括有符号整型和无符号整型。统一定义为int,后面带上数字表示占用的字节数

整型范围

  • int8-[-128:127]占用8个字节,对应java中的byte
  • int16-[-32768:23767]占用16个字节,对应short
  • int32-[-2147483648:2147483647]占用32个字节,对应int
  • int64-[-9223372036854775808:9223372036854775807]占用64个字节,对应long

无符号整型范围

  • Uint8-[0:255]
  • Uint16-[0:65535]
  • Uint32-[0:4294967295]
  • Uint64-[0:18446744073709551615]

boolean布尔类型

CK中没有定义表述true和false的布尔类型数据,通常都是直接使用Unit8

浮点型

  • Float32 – float
  • Float64 – double

官方建议尽量使用整型来存储数据,将固定精度的数字转换成为整数值。例如时间为毫秒为单位的保存。这是因为使用浮点型有精准度的丢失问题,例如执行select 1-0.9的出的结果将是0.09999999999999998而不是0.1。

浮点型一般用于数据值比较小,不涉及大量的统计计算,精度要求也不高的场景。例如保存商品重量,但是对于精度要求比较高的就不建议使用了

decimal型

有符号的浮点数,可以在加、减和乘法运算过程汇总保存精度。对于除法,最低有效数字将被抛弃(不会四舍五入)。通常有三种声明:Decimal32(s)、Decimal64(s)、Decimal128(s)。后面的s表示小数点后的数字位数,前面的32、64、128表示浮点精度,决定可以有多少个十进制数字(包含小数位),也就代表不同的取值范围。

数据在底层会采用与自身位宽相同的有符号整数存储。而现代CPU不支持128位的数字,因此Decimal128上的操作需要由软件来进行模拟,所以decimal的运算速度会明显比前面两个慢,也就是说尽量少用decimal128

字符串

CK的字符型数据使用String进行声明。这个字符串可以是任意长度的,包括任意字符集,包含空字节。因此,字符串类型可以代替其他数据库中的varchar、blob、clob等类型。

ck中没有编码的概念,字符串可以是任意的字节集,按他们原本的方式进行存储和输出,对于不同版本的编码文本,CK会有不同处理字符串的函数。比如length函数可以计算字符串包含的字节数组的长度,而lengthUTF8函数是假设字符串以UTF-8编码,计算的字符串包含的unicode字符的长度。

还有个固定长度的字符串类型FixdString(N),这个N就是要声明的字节数。如果字符串包含字节数不足N,将会对字符串末尾进行空字节填充。如果字符串包含的字节数大于N,将会抛出异常。可以用来保存一些例如手机号码、IP地址这一类等长的规范数据,在实际开发中使用比较少

枚举型

包含Enum8和Enum16两种类型,Enum保存’string’=integer的对应关系。在CK中,尽管用户使用的是字符串常量,但所有罕有Enum数据类型的操作都是按照包含整数来执行的,这在性能方面比使用String数据类型更有效。

Enum后面的8和16也是对应整数值integer的位宽

例如:先创建一个带枚举类型列的表。

CREATE TABLE t_enum
(
x Enum(‘hello’ = 1,’word’ = 2)
)
engine = TinyLog;

这个x列只能存储数据类型定义中列出来的值,hello或者是word,尝试inster插入其他值是会抛出异常

insert into t_enum values (‘hello’),(‘word’),(‘hello’);

SELECT *
FROM t_enum

Query id: 909b3648-e63c-4316-96fd-a003f95abd58

┌─x─────┐
│ hello │
│ word │
│ hello │
└───────┘

3 rows in set. Elapsed: 0.006 sec.

 

insert into t_enum values (‘hello’),(‘word’),(‘abc’);
INSERT INTO t_enum VALUES

Query id: 6ea3cfba-1bf8-4d1e-ae0e-f1854f28579f

Exception on client:
Code: 36. DB::Exception: Unknown element ‘abc’ for enum: While executing ValuesBlockInputFormat: data for INSERT was parsed from query. (BAD_ARGUMENTS)

Connecting to database test at localhost:9000 as user default.
Connected to ClickHouse server version 21.9.7 revision 54449.

 

select cast (x,’Int8′) from t_enum;
SELECT cast(x, ‘Int8’)
FROM t_enum

Query id: 22daf08d-c6ab-4581-916b-68e90b5a6f3c

┌─CAST(x, ‘Int8’)─┐
│ 1 │
│ 2 │
│ 1 │
└─────────────────┘

3 rows in set. Elapsed: 0.002 sec.

insert into t_enum values (1);

INSERT INTO t_enum VALUES

Query id: 9cdec16d-a370-4283-b8d9-cc9a964ad926

Ok.

1 rows in set. Elapsed: 0.003 sec.

 

数组类型

类型声明:array(T)。表示一个由T类型元素组成的数组,T可以是任意类型,甚至也可以是数组类型。但是不建议使用多位数组,clickhouse对多维数组的支持有限,例如在MergeTree引擎中就不能存储多维数组。

select array(1,2) AS x, toTypeName(x) ;

SELECT
[1, 2] AS x,
toTypeName(x)

Query id: e317cfe0-b9c4-4945-aa2d-bc8abc973064

┌─x─────┬─toTypeName(array(1, 2))─┐
│ [1,2] │ Array(UInt8) │
└───────┴─────────────────────────┘

1 rows in set. Elapsed: 0.002 sec.

时间类型

时间类型是每个数据库都要处理的类型。CK的时间类型声明相对简单很多。在CK中有三种时间类型

  • Dtae 可以接受一个年-月-日格式的字符串。例如‘2021-10-13’
  • Datetime 可以接受一个年-月-日 时:分:秒 格式的字符串
  • Datetime64 可以接受一个 年-月-日 时:分:秒.毫秒 格式的字符串

可为空类型

绝大部分的基础类型都可以通过前面的添加Nullable()声明来允许接受Null空值。例如Nullable(Int8)类型的列可以存储Int8类型的值,没有值得行将存储Null

Nullable类型字段不能包含在彪索引中,并且使用Nullable几乎总是对性能产生负面影响,在设计数据库时要尽量避免使用Nullable,例如对于字符串,可以用空字符代替Null,而对于整型数据,可以用无业务意义的数字例如-1表示NUll

create table t_null ( x Int8, y Nullable(Int8)) engine TinyLog;
INSERT INTO t_null VALUES (1,NULL),(2,3);
SELECT x+y FROM t_null;
SELECT x + y
FROM t_null

Query id: 59b60442-a09f-4dce-8c69-7fec076042e9

┌─plus(x, y)─┐
│ ᴺᵁᴸᴸ │
│ 5 │
└────────────┘

2 rows in set. Elapsed: 0.002 sec.

CK中还涉及非常多有特色的数据类型,例如Geo,Map,Tuple,UUID等类型,具体参见官方文档https://clickhouse.com/docs/zh/sql-reference/data-types/