进入正文前,感谢宝子们订阅专题、点赞、评论、收藏!关注IT贫道,获取高质量博客内容!
🏡个人主页:含各种IT体系技术,IT贫道_Apache Doris,Kerberos安全认证,大数据OLAP体系技术栈-CSDN博客
📌订阅:拥抱独家专题,你的订阅将点燃我的创作热情!
👍点赞:赞同优秀创作,你的点赞是对我创作最大的认可!
⭐️ 收藏:收藏原创博文,让我们一起打造IT界的荣耀与辉煌!
✏️评论:留下心声墨迹,你的评论将是我努力改进的方向!
目录
11. 枚举类型 Enum
12. Nullable
13. 数组类型 Array(T)
14. Tuple类型
15. 嵌套类型Nested
16. Domain
11. 枚举类型 Enum
枚举类型通常在定义常量时使用,ClickHouse提供了Enum8和Enum16两种枚举类型。Enum保存'string'=integer的对应关系。在 ClickHouse 中,尽管用户使用的是字符串常量,但所有含有 Enum 数据类型的操作都是按照包含整数的值来执行。这在性能方面比使用 String 数据类型更有效。
Enum8和Enum16分别对应'String'=Int8和'String'=Int16,Enum8类型的每个值范围是-128 ... 127,Enum16类型的每个值范围是-32768 ... 32767,所有的字符串或者数字都必须是不一样的,允许存在空字符串,Enum类型中数字可以是任意顺序,顺序并不重要。
向Enum字段中插入值时,可以插入枚举的字符串值也可以插入枚举对应的Int值,建议插入对应的字符串值,这样避免插入对应的Int值不在Enum枚举集合中再次查询表时报错。定义了枚举类型值之后,不能写入其他值的数据,写入的值不在枚举集合中就会抛出异常。
- 示例:
#创建一个表,带有Enum类型的列node1 :) CREATE TABLE t_enum(x Enum8('hello' = 1, 'world' = 2)) ENGINE = TinyLog#向表中插入数据node1 :) insert into t_enum values('hello'),(2);#查询结果node1 :) select * from t_enum;SELECT *FROM t_enum┌─x─────┐│ hello ││ world │└───────┘2 rows in set. Elapsed: 0.003 sec.#插入不在枚举集合中的值时,抛出异常node1 :) insert into t_enum values ('aa')INSERT INTO t_enum VALUESException on client:Code: 36. DB::Exception: Unknown element 'aa' for type Enum8('hello' = 1, 'world' = 2)Connecting to database mydb at localhost:9000 as user default.Connected to ClickHouse server version 20.8.3 revision 54438.#使用枚举类型代替boolean类型。建表,并插入数据node1 :) CREATE TABLE t_enum2(bl Enum8('true' = 1, 'false' = 0)) ENGINE = TinyLog;node1 :) insert into t_enum2 values(0),(1);node1 :) select * from t_enum2;SELECT *FROM t_enum2┌─bl────┐│ false ││ true │└───────┘2 rows in set. Elapsed: 0.004 sec.#查询时可以通过函数将对应的Enum底层数值获取出来node1 :) select toInt8(bl) from t_enum2;SELECT toInt8(bl)FROM t_enum2┌─toInt8(bl)─┐│ 0 ││ 1 │└────────────┘2 rows in set. Elapsed: 0.004 sec.
12. Nullable
Nullable类型只能与基础数据类型搭配使用,表示某个类型的值可以为NULL,Nullable(Int8)表示可以存储Int8类型的值,没有值时存NULL。使用Nullable需要注意:Nullable类型的字段不能作为索引字段,尽量避免使用Nullable类型,因为字段被定义为Nullable类型后会额外生成[Column].null.bin文件保存Null值,增加开销,比普通列消耗更多的存储空间。
- 示例:
#创建表,含有Nullable类型的列node1 :) CREATE TABLE t_null(x Int8, y Nullable(Int8)) ENGINE TinyLog;#向表 t_null中插入数据node1 :) INSERT INTO t_null VALUES (1, NULL), (2, 3);#查询表t_null中的数据node1 :) select * from t_null;SELECT *FROM t_null┌─x─┬────y─┐│ 1 │ ᴺᵁᴸᴸ ││ 2 │ 3 │└───┴──────┘2 rows in set. Elapsed: 0.007 sec#查询表t_null做简单运算node1 :) SELECT x + y FROM t_null;SELECT x + yFROM t_null┌─plus(x, y)─┐│ ᴺᵁᴸᴸ ││ 5 │└────────────┘2 rows in set. Elapsed: 0.004 sec.
13. 数组类型 Array(T)
Array(T),由 T 类型元素组成的数组。T 可以是任意类型,包含数组类型。但不推荐使用多维数组,ClickHouse对多维数组的支持有限。例如,不能在MergeTree表中存储多维数组。
数组的定义方式有两种:Array(T),[1,2,3... ...],数组类型里面的元素必须具有相同的数据类型,否则会报异常。另外,需要注意的是,数组元素中如果存在Null值,则元素类型将变为Nullable。
从数组中查询获取值使用 xx[1|2.. ...],直接使用中括号获取值,下标从1开始。
- 示例:
#两种方式定义数组node1 :) SELECT array(1, 2) AS x, toTypeName(x),['zs','ls','ww'] as y ,toTypeName(y)SELECT[1, 2] AS x,toTypeName(x),['zs', 'ls', 'ww'] AS y,toTypeName(y)┌─x─────┬─toTypeName(array(1, 2))─┬─y────────────────┬─toTypeName(['zs', 'ls', 'ww'])─┐│ [1,2] │ Array(UInt8) │ ['zs','ls','ww'] │ Array(String) │└───────┴─────────────────────────┴──────────────────┴────────────────────────────────┘1 rows in set. Elapsed: 0.004 sec.# 数组中有Null,则数组类型为Nullablenode1 :) SELECT array(1, 2, NULL) AS x, toTypeName(x);SELECT[1, 2, NULL] AS x,toTypeName(x)┌─x──────────┬─toTypeName(array(1, 2, NULL))─┐│ [1,2,NULL] │ Array(Nullable(UInt8)) │└────────────┴───────────────────────────────┘1 rows in set. Elapsed: 0.006 sec.#数组类型里面的元素必须具有相同的数据类型,否则会报异常node1 :) SELECT array(1, 'a')SELECT [1, 'a']Received exception from server (version 20.8.3):Code: 386. DB::Exception: Received from localhost:9000. DB::Exception: There is no supertype for types UInt8, String because some of them are String/FixedString and some of them are not.0 rows in set. Elapsed: 0.005 sec.#创建表,含有array(T)类型字段,并插入数据node1 :) create table t_array(id UInt32,name String,score Array(UInt32)) ENGINE = TinyLog;#插入数据,注意:字符串在clickhouse中只能是单引号node1 :) insert into t_array values (1,'zs',array(10,20,30)),(2,'ls',[100,200,300])#数组内获取值node1 :) select id,name,score[1] from t_array;SELECTid,name,score[1]FROM t_array┌─id─┬─name─┬─arrayElement(score, 1)─┐│ 1 │ zs │ 10 ││ 2 │ ls │ 100 │└──┴─── ─┴───────────────┘5 rows in set. Elapsed: 0.004 sec.
14. Tuple类型
元组类型有1~n个元素组成,每个元素允许设置不同的数据类型,且彼此之间不要求兼容。与数组类似,元组也可以使用两种方式定义:tuple(1,'hello',12.34)或者直接写(1,'hello',45.67),元组中可以存储多种数据类型,但是要注意数据类型的顺序。
- 示例:
#创建元组node1 :) SELECT tuple(1,'a') AS x, toTypeName(x),(1,'b','hello') AS y ,toTypeName(y)SELECT(1, 'a') AS x,toTypeName(x),(1, 'b', 'hello') AS y,toTypeName(y)┌─x───────┬─toTypeName(tuple(1, 'a'))─┬─y───────────────┬─toTypeName(tuple(1, 'b', 'hello'))─┐│ (1,'a') │ Tuple(UInt8, String) │ (1,'b','hello') │ Tuple(UInt8, String, String) │└─────────┴───────────────────────────┴─────────────────┴────────────────────────────────────┘1 rows in set. Elapsed: 0.004 sec.#建表,含有元组类型node1 :) create table t_tuple(id UInt8,name String,info Tuple(String,UInt8)) engine = TinyLog#插入数据node1 :) insert into t_tuple values (1,'zs',tuple('cls1',100)),(2,'ls',('cls2',200))#查询数据node1 :) select * from t_tuple;SELECT *FROM t_tuple┌─id─┬─name─┬─info─────────┐│ 1 │ zs │ ('cls1',100) ││ 2 │ ls │ ('cls2',200) │└────┴──────┴──────────────┘2 rows in set. Elapsed: 0.003 sec.
15. 嵌套类型Nested
ClickHouse支持嵌套数据类型(Nested),可以为一个表定义一个或者多个嵌套数据类型字段,但是每个嵌套字段只支持一级嵌套,即嵌套字段内不能继续使用嵌套类型。嵌套一般用来表示简单的级联关系,嵌套本质上是一个多维数组,嵌套类型中的每个数组的长度必须相同。目前,Nested类型支持很局限,MergeTree引擎中不支持Nested类型。
- 示例:
#创建一个表,每个人可以属于多个部门,在不同部门有不同的编号idnode1 :) create table t_nested(:-] id UInt8,:-] name String,:-] dept Nested(:-] id UInt8,:-] name String:-] )) engine = TinyLog;#查看表t_nested的表结构node1 :) desc t_nested;DESCRIBE TABLE t_nested┌─name──────┬─type──────────┬│ id │ UInt8 ││ name │ String ││ dept.id │ Array(UInt8) ││ dept.name │ Array(String) │└───────────┴───────────────┴4 rows in set. Elapsed: 0.003 sec.#向表t_nested中插入数据node1 :) insert into t_nested values (1,'zs',[10,11,12],['dp1','dp2','dp3']),(2,'ls',[100,101],['dp4','dp5'])#查询表 t_nested数据,可以获取嵌套类型中部分字段node1 :) select *,dept.name[1] as first_dpt from t_nested;SELECT*,dept.name[1] AS first_dptFROM t_nested┌─id─┬─name─┬─dept.id────┬─dept.name───────────┬─first_dpt─┐│ 1 │ zs │ [10,11,12] │ ['dp1','dp2','dp3'] │ dp1 ││ 2 │ ls │ [100,101] │ ['dp4','dp5'] │ dp4 │└────┴──────┴────────────┴─────────────────────┴───────────┘2 rows in set. Elapsed: 0.004 sec.
16. Domain
Domain类型是特定实现的类型,目前支持IPv4和IPv6两类,本质上他们是对整形和字符串的进一步封装,IPv4类型基于UInt32封装,IPv6基于FixedString(16)封装。
出于便捷性的考量,例如:IPv4类型支持格式检查,格式错误的IP无法被写入。出于性能的考量,IPv4和IPv6相对于String更加紧凑,占用的空间更小,查询性能更快。
在使用Domain时需要注意,虽然表面看起来与String一样,但是Domain类型并不是字符串,也不支持隐式自动转换成字符串,如果需要返回IP的字符串形式,需要调用函数IPv4NumToString()和IPv6NumToString()显式实现。
- 示例:(示例以IPv4为例,IPv6同理)
#创建表 t_domain 含有IPv4字段node1 :) CREATE TABLE t_domain(url String, from IPv4) ENGINE = TinyLog;#插入数据node1 :) INSERT INTO t_domain(url, from) VALUES ('https://wikipedia.org', '116.253.40.133')('https://clickhouse.tech', '183.247.232.58')('https://clickhouse.tech/docs/en/', '116.106.34.242');#查看表 t_domain结果数据node1 :) select * from t_domain;SELECT *FROM t_domain┌─url──────────────────────────────┬───────────from─┐│ https://wikipedia.org │ 116.253.40.133 ││ https://clickhouse.tech │ 183.247.232.58 ││ https://clickhouse.tech/docs/en/ │ 116.106.34.242 │└───────────────────────────────────┴────────────────┘3 rows in set. Elapsed: 0.004 sec.#插入数据不符合IP格式会报错node1 :) INSERT INTO t_domain(url, from) VALUES ('https://www.baidu.com', '116.253.40')INSERT INTO t_domain (url, from) VALUESException on client:Code: 441. DB::Exception: Invalid IPv4 value.Connecting to database mydb at localhost:9000 as user default.Connected to ClickHouse server version 20.8.3 revision 54438.#将表 t_domain 中from IPv4类型转换成String类型node1 :) SELECT from,toTypeName(from) as tp1,toTypeName(s) as tp2, IPv4NumToString(from) as s FROM t_domain;SELECTfrom,toTypeName(from) AS tp1,toTypeName(s) AS tp2,IPv4NumToString(from) AS sFROM t_domain┌───────────from─┬─tp1──┬─tp2────┬─s──────────────┐│ 116.253.40.133 │ IPv4 │ String │ 116.253.40.133 ││ 183.247.232.58 │ IPv4 │ String │ 183.247.232.58 ││ 116.106.34.242 │ IPv4 │ String │ 116.106.34.242 │└────────────────┴──────┴────────┴────────────────┘3 rows in set. Elapsed: 0.003 sec.
👨💻如需博文中的资料请私信博主。