客快物流大数据项目(八十九):ClickHouse的数据类型支持
ClickHouse的数据类型支持
ClickHouse与常用的关系型数据库MySQL或Oracle的数据类型类似,提供了丰富的数据类型支持。
一、整型
ClickHouse支持Int和Uint两种固定长度的整型,Int类型是符号整型,Uint类型是无符号整型。
分类 |
数据类型 |
取值范围 |
---|---|---|
整型 |
Int8 |
-128 ~ 127 |
|
Int16 |
-32768 ~ 32767 |
|
Int32 |
-2147483648 ~ 2147483647 |
|
Int64 |
-9223372036854775808 ~ 223372036854775807 |
无符号整型 |
UInt8 |
0 ~ 255 |
|
Uint16 |
0 ~ 65535 |
|
Uint32 |
0 ~ 4294967295 |
|
Uint64 |
0 ~ 18446744073709551615 |
二、浮点型
ClickHouse支持Float32和Float64两种浮点类型,浮点型在运算时可能会导致一些问题,例如计算的结果取决于计算机的处理器和操作系统、可能是正无穷或负无穷等问题,官方建议尽量以整数形式存储数据。例如,将固定精度的数字转换为整数值,例如货币数量或页面加载时间用毫秒为单位表示。
select 1-0.9 的结果是0.09999999999999998
select 1/0的结果是 inf(正无穷)
select -1/0的结果是 -inf(负无穷)
select 0/0的结果是 nan(非数字)
三、Decimal
ClickHouse支持Decimal类型的有符号定点数,可在加、减和乘法运算过程中保持精度。对于除法,最低有效数字会被丢弃,但不会四舍五入。数据采用与自身位宽相同的有符号整数存储。这个数在内存中实际范围会高于上述范围,从 String 转换到十进制数的时候会做对应的检查。由于现代CPU不支持128位数字,因此 Decimal128 上的操作由软件模拟。
所以 Decimal128 的运算速度明显慢于 Decimal32/Decimal64。
Decimal(P,S),P参数指的是精度,有效范围:[1:38],决定可以有多少个十进制数字(包括分数);S参数指的是小数长度,有效范围:[0:P],决定数字的小数部分中包含的小数位数。
数据类型 |
十进制的范围 |
---|---|
Decimal32(S) |
Decimal32(S): ( -1 * 10^(9 - S), 1 * 10^(9 - S) ) |
Decimal64(S) |
Decimal64(S): ( -1 * 10^(18 - S), 1 * 10^(18 - S) ) |
Decimal128(S) |
Decimal128(S): ( -1 * 10^(38 - S), 1 * 10^(38 - S) ) |
对Decimal的二进制运算导致更宽的结果类型,两个不同的Decimal类型在运算时精度的变化规则如下:
例子 |
Decimal64(S1) Decimal32(S2) -> Decimal64(S) Decimal128(S1) Decimal32(S2) -> Decimal128(S) Decimal128(S1) Decimal64(S2) -> Decimal128(S) |
---|---|
小数变化规则 |
加法,减法:S = max(S1, S2) 乘法:S = S1 + S2 除法:S = S1 |
四、布尔型
ClickHouse中没有定义布尔类型,可以使用UInt8类型,取值限制为0或1。
五、字符串类型
ClickHouse中的String类型没有编码的概念。字符串可以是任意的字节集,按它们原本的方式进行存储和输出。若需存储文本,建议使用UTF-8编码。至少,如果你的终端使用UTF-8,这样读写就不需要进行任何的转换。对不同的编码文本ClickHouse会有不同处理字符串的函数。比如,length函数可以计算字符串包含的字节数组的长度,然而lengthUTF8函数是假设字符串以 UTF-8编码,计算的是字符串包含的Unicode字符的长度。
数据类型 |
十进制的范围 |
---|---|
String |
字符串可以任意长度的。它可以包含任意的字节集,包含空字节。ClickHouse中的String类型可以代替其他DBMS中的VARCHAR、BLOB、CLOB等类型。 |
FixedString(N) |
固定长度 N 的字符串,N必须是严格的正自然数。当服务端读取长度小于N的字符串时候,通过在字符串末尾添加空字节来达到N字节长度。当服务端读取长度大于N的字符串时候,将返回错误消息。与String相比,极少会使用FixedString,因为使用起来不是很方便。 1)在插入数据时,如果字符串包含的字节数小于N,将对字符串末尾进行空字节填充。如果字符串包含的字节数大于N,将抛Too large value for FixedString(N)异常。 2)在查询数据时,ClickHouse不会删除字符串末尾的空字节。如果使用WHERE子句,则须要手动添加空字节以匹配FixedString的值(例如:where a=’abc\0’)。 注意,FixedString(N)的长度是个常量。仅由空字符组成的字符串,函数length返回值为N,而函数empty的返回值为1。 |
六、UUID
ClickHouse支持UUID类型(通用唯一标识符),该类型是一个16字节的数字,用于标识记录。ClickHouse内置generateUUIDv4函数来生成UUID值,UUID数据类型仅支持String数据类型也支持的函数(例如,min,max和count)。
七、Date类型
ClickHouse支持Date类型,这个日期类型用两个字节存储,表示从 1970-01-01 (无符号) 到当前的日期值。允许存储从 Unix 纪元开始到编译阶段定义的上限阈值常量(目前上限是2106年,但最终完全支持的年份为2105),最小值输出为0000-00-00。日期类型中不存储时区信息。
八、DateTime类型
ClickHouse支持DataTime类型,这个时间戳类型用四个字节(无符号的)存储Unix时间戳。允许存储与日期类型相同范围内的值,最小值为0000-00-00 00:00:00。时间戳类型值精确到(不包括闰秒)。
使用客户端或服务器时的系统时区,时间戳是从文本转换为二进制并返回。在文本格式中,有关夏令时的信息会丢失。
默认情况下,客户端连接到服务的时候会使用服务端时区。您可以通过启用客户端命令行选项--use_client_time_zone 来设置使用客户端时间。
因此,在处理文本日期时(例如,在保存文本转储时),请记住在夏令时更改期间可能存在歧义,如果时区发生更改,则可能存在匹配数据的问题。
九、枚举类型
ClickHouse支持Enum8和Enum16两种枚举类型。Enum保存的是'string'=integer的对应关系。在 ClickHouse中,尽管用户使用的是字符串常量,但所有含有Enum 数据类型的操作都是按照包含整数的值来执行,这在性能方面比使用String数据类型更有效。
在ORDER BY、GROUP BY、IN、DISTINCT等函数中,Enum 的行为与相应的数字作用相同。例如,按数字排序。对于等式运算符和比较运算符,Enum 的工作机制与它们在底层数值上的工作机制相同。
Enum中的字符串和数值都不允许为NULL,当声明表字段时使用Nullable类型包含Enum类型时,在插入数据时允许NULL值。Enum类型提供toString函数来返回字符串值;toT函数可以转换为数值类型,T表示一个数值类型,如果T恰好对应Enum底层的数值类型则这个转换是0成本的。Enum类型可以使用Alter无成本修改对应集合的值,可以使用Alter来添加或删除Enum的成员(出于安全保障,如果改变之前用过的Enum会报异常),也可以用Alter将Enum8转换为Enum16或反之。
数据类型 |
String=Integer对应关系 |
取值范围 |
---|---|---|
Enum8 |
'String'= Int8 |
-128 ~ 127 |
Enum16 |
'String'= Int16 |
-32768 ~ 32767 |
- 创建tbl_test_enum表
create table tbl_test_enum(e1 Enum8('male'=1, 'female'=2),e2 Enum16('hello'=1,'word'=2), e3 Nullable(Enum8('A'=1, 'B'=2)),e4 Nullable(Enum16('a'=1,'b'=2))) engine=TinyLog;
- 插入字符串数据
insert into tbl_test_enum values('male', 'hello', 'A', null),('male', 'word', null, 'a');
insert into tbl_test_enum values(2, 1, 'C', null);
- 查询结果
select * from tbl_test_enum;
十、数组类型
ClickHouse支持Array(T)类型,T可以是任意类型,包括数组类型,但不推荐使用多维数组,因为对其的支持有限(MergeTree引擎表不支持存储多维数组)。T要求是兼容的数据类型,因为ClickHouse会自动检测并根据元素内容计算出存储这些数据的最小数据类型,如:不能使用array(1,’hello’)。
- 数组声明的两种方式
select array(1,3,5) as arr1,[2,4,6] as arr2, toTypeName(arr1) as arrType1, toTypeName(arr2) as arrType2;
十一、AggregateFunction类型
AggregateFunction(name,type_of_arguments)
create table aggMT (whatever Date default '2019-12-18',key String,value String,first AggregateFunction(min, DateTime),last AggregateFunction(max, DateTime),total AggregateFunction(count,UInt64)) ENGINE=AggregatingMergeTree(whatever,(key,value),8192);
insert into aggMT (key,value,first,last,total) select 'test','1.2.3.4',minState(toDateTime(1576654217)),maxState(toDateTime(1576654217)),countState(cast(1 as UInt64));
insert into aggMT (key,value,first,last,total) select 'test','1.2.3.5',minState(toDateTime(1576654261)),maxState(toDateTime(1576654261)),countState(cast(1 as UInt64));
insert into aggMT (key,value,first,last,total) select 'test','1.2.3.6',minState(toDateTime(1576654273)),maxState(toDateTime(1576654273)),countState(cast(1 as UInt64));
select key, value,minMerge(first),maxMerge(last),countMerge(total) from aggMT group by key, value;
十二、元组类型
ClickHouse提供Tuple类型支持,Tuple(T1,T2...)中每个元素都可以是单独的类型。除了内存表以外,元组中不可以嵌套元组,但可以用于临时列分组。在查询中,使用IN表达式和带特定参数的lambda函数可以来对临时列进行分组。元组可以是查询的结果。在这种情况下,对于JSON以外的文本格式,括号中的值是逗号分隔的。在JSON格式中,元组作为数组输出(在方括号中)。在动态创建元组时,ClickHouse 会自动为元组的每一个参数赋予最小可表达的类型。如果参数值为NULL则这个元组对应元素类型是Nullable。
- 使用元组的例子1:
select tuple(1, 'a') as x, toTypeName(x);
- 使用元组传入null值时自动推断类型例子2:
select tuple(1, null) as x, toTypeName(x);
十三、Nullable类型
ClickHouse支持Nullable类型,该类型允许用NULL来表示缺失值。Nullable字段不能作为索引列使用,在ClickHouse的表中存储Nullable列时,会对性能产生一定影响。
默认情况下,字段是不允许为NULL的。例如有个Int8类型的字段,在插入数据时有可能为NULL,需要将字段类型声明为Nullable(Int8)。
- 创建测试表tbl_test_nullable
create table tbl_test_nullable(f1 String, f2 Int8, f3 Nullable(Int8)) engine=TinyLog;
- 插入非null值到tbl_test_nullable表(成功)
insert into tbl_test_nullable(f1,f2,f3) values('NoNull',1,1);
- f1字段为null值时插入到tbl_test_nullable表(失败)
insert into tbl_test_nullable(f1,f2,f3) values(null,2,2);
- f2字段为null值时插入到tbl_test_nullable表(失败)
insert into tbl_test_nullable(f1,f2,f3) values('NoNull2',null,2);
- f3字段为null值时插入到tbl_test_nullable表(成功)
insert into tbl_test_nullable(f1,f2,f3) values('NoNull2',2,null);
- 查询tbl_test_nullable表(有2条记录)
select * from tbl_test_nullable;
十四、嵌套数据结构
ClickHouse支持嵌套数据结构,可以简单地把嵌套数据结构当做是所有列都是相同长度的多列数组。创建表时,可以包含任意多个嵌套数据结构的列,但嵌套数据结构的列仅支持一级嵌套。嵌套列在insert时,需要把嵌套列的每一个字段以[要插入的值]格式进行数据插入。
- 创建带嵌套结构字段的表
create table tbl_test_nested(uid Int64, ctime date, user Nested(name String, age Int8, phone Int64), Sign Int8) engine=CollapsingMergeTree(ctime,intHash32(uid),(ctime,intHash32(uid)),8192,Sign);
- 插入数据
insert into tbl_test_nested values(1,'2022-12-3',['zhangsan'],[23],[13800138000],1);
- 查询uid=1并且user嵌套列的age>=20的数据
select * from tbl_test_nested where uid=1 and arrayFilter(u -> u >= 20, user.age) != [];
- 查询user嵌套列name=zhangsan的数据
select * from tbl_test_nested where hasAny(user.name,['zhangsan']);
- 模糊查询user嵌套列name=zhang的数据
select * from tbl_test_nested where arrayFilter(u -> u like '%zhang%', user.name) != [];
十五、interval
Interval是ClickHouse提供的一种特殊的数据类型,此数据类型用来对Date和Datetime进行运算,不能使用Interval类型声明表中的字段。
Interval支持的时间类型有SECOND、MINUTE、HOUR、DAY、WEEK、MONTH、QUARTER和YEAR。对于不同的时间类型参数,都有一个单独的数据类型,如下表格。
时间类型参数 |
查询Interval类型 |
Interval类型 |
---|---|---|
SECOND |
SELECT toTypeName(INTERVAL 4 SECOND); |
IntervalSecond |
MINUTE |
SELECT toTypeName(INTERVAL 4 MINUTE); |
IntervalMinute |
HOUR |
SELECT toTypeName(INTERVAL 4 HOUR); |
IntervalHour |
DAY |
SELECT toTypeName(INTERVAL 4 DAY); |
IntervalDay |
WEEK |
SELECT toTypeName(INTERVAL 4 WEEK); |
IntervalWeek |
MONTH |
SELECT toTypeName(INTERVAL 4 MONTH); |
IntervalMonth |
QUARTER |
SELECT toTypeName(INTERVAL 4 QUARTER); |
IntervalQuarter |
YEAR |
SELECT toTypeName(INTERVAL 4 YEAR); |
IntervalYear |
- 获取当前时间+4天的时间
select now() as cur_dt, cur_dt + interval 4 DAY plus_dt;
- 获取当前时间+4天+3小时的时间
select now() as cur_dt, cur_dt + interval 4 DAY + interval 3 HOUR as plus_dt;
十六、IPv4类型与IPv6类型
ClickHouse支持IPv4和Ipv6两种Domain类型,Ipv4类型是与UInt32类型保持二进制兼容的Domain类型,其用于存储IPv4地址的值;
IPv6是与FixedString(16)类型保持二进制兼容的Domain类型,其用于存储IPv6地址的值。
这两种Domain类型提供了更为紧凑的二进制存储的同时支持识别可读性更加友好的输入输出格式。
- 创建tbl_test_domain表
create table tbl_test_domain(url String, ip4 IPv4, ip6 IPv6) ENGINE = MergeTree() ORDER BY url;
- 插入IPv4和IPv6类型字段数据到tbl_test_domain表
insert into tbl_test_domain(url,ip4,ip6) values('https://www.lansonli.com','127.0.0.1','2a02:aa08:e000:3100::2');
- 查询tbl_test_domain表数据
select * from tbl_test_domain;
- 查询类型和二进制格式
select url,toTypeName(ip4) as ip4Type, hex(ip4) as ip4Hex,toTypeName(ip6) as ip6Type, hex(ip6) as ip6Hex from tbl_test_domain;
- 使用IPv4NumToString和IPv6NumToString将Domain类型转换为字符串
select url,IPv4NumToString(ip4) as ip4Str,IPv6NumToString(ip6) as ip6Str from tbl_test_domain;
十七、默认值处理
在ClickHouse中,对于某些类型的列,在没有显示插入值时,会自动填充默认值处理。
数据类型 |
默认值 |
---|---|
Int和Uint |
0 |
String |
空字符串 |
Array |
空数组 |
Date |
0000-00-00 |
DateTime |
0000-00-00 00:00:00 |
NULL |
不支持 |
- 点赞
- 收藏
- 关注作者
评论(0)