2

ClickHouse(05)ClickHouse数据类型详解 - 张飞的猪

 2 years ago
source link: https://www.cnblogs.com/the-pig-of-zf/p/16653568.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

ClickHouse(05)ClickHouse数据类型详解

ClickHouse属于分析型数据库,ClickHouse提供了许多数据类型,它们可以划分为基础类型、复合类型和特殊类型。其中基础类型使ClickHouse具备了描述数据的基本能力,而另外两种类型则使ClickHouse的数据表达能力更加丰富立体。

基础类型只有数值、字符串和时间三种类型,没有Boolean类型,但可以使用整型的0或1替代。

数值类型分为整数、浮点数和定点数三类,接下来分别进行说明。

在普遍观念中,常用Tinyint、Smallint、Int和Bigint指代整数的不同取值范围。而ClickHouse则直接使用Int8、Int16、Int32和Int64指代4种大小的Int类型,其末尾的数字正好表明了占用字节的大小(8位=1字节)。

ClickHouseInt数据类型
ClickHouse无符号Int数据类型

Float

与整数类似,ClickHouse直接使用Float32和Float64代表单精度浮点数以及双精度浮点数。在使用浮点数的时候,要意识到它是有限精度的。对Float32和Float64写入超过有效精度的数值,结果就会出现数据误差,会被截断。

ClickHouseFloat数据类型

另外,ClickHousae对于正无穷、负无穷、以及非数值类型的表示。

  • 正无穷:inf
  • 负无穷:-inf
  • 非数值类型:

Decimal

要更高精度的数值运算,需要使用定点数。ClickHouse提供了Decimal32、Decimal64和Decimal128三种精度的定点数。可以通过两种形式声明定点:简写方式有Decimal32(S)、Decimal64(S)、Decimal128(S)三种,原生方式为Decimal(P,S),其中:

  • P代表精度,决定总位数(整数部分+小数部分),取值范围是1~38;
  • S代表规模,决定小数位数,取值范围是0~P。

ClickHouseDecimal数据类型

字符串类型

字符串类型可以细分为String、FixedString和UUID三类。

String

字符串由String定义,长度不限。因此在使用String的时候无须声明大小。它完全代替了传统意义上数据库的Varchar、Text、Clob和Blob等字符类型。String类型不限定字符集,因为它根本就没有这个概念,所以可以将任意编码的字符串存入其中。

FixedString

FixedString类型和传统意义上的Char类型有些类似,对于一些字符有明确长度的场合,可以使用固定长度的字符串。定长字符串通过FixedString(N)声明,其中N表示字符串长度。但与Char不同的是,FixedString使用null字节填充末尾字符,而Char通常使用空格填充。比如在下面的例子中,字符串‘abc’虽然只有3位,但长度却是5,因为末尾有2位空字符填充。

UUID是一种数据库常见的主键类型,在ClickHouse中直接把它作为一种数据类型。UUID共有32位,它的格式为8-4-4-4-12。如果一个UUID类型的字段在写入数据时没有被赋值,则会依照格式使用0填充。

时间类型分为DateTime、DateTime64和Date三类。ClickHouse目前没有时间戳类型。时间类型最高的精度是秒,也就是说,如果需要处理毫秒、微秒等大于秒分辨率的时间,则只能借助UInt类型实现。

DateTime

DateTime类型包含时、分、秒信息,精确到秒。

DateTime64

DateTime64可以记录亚秒,它在DateTime之上增加了精度的设置。

Date类型不包含具体的时间信息,只精确到天。

ClickHouse还提供了数组、元组、枚举和嵌套四类复合类型。

数组Array

数组有两种定义形式,常规方式array(T),或者简写方式[T]。在同一个数组内可以包含多种数据类型,例如数组[1,2.0]是可行的。但各类型之间必须兼容,例如数组[1,'2']则会报错。

在查询时并不需要主动声明数组的元素类型。因为ClickHouse的数组拥有类型推断的能力,推断依据:以最小存储代价为原则,即使用最小可表达的数据类型。

--常规定义方式SELECT array(1, 2) as a , toTypeName(a)┌─a───┬─toTypeName(array(1, 2))─┐│ [1,2] │ Array(UInt8) │└─────┴────────────────┘ --简写定义方式SELECT [1, 2] --建表时数据类型定义CREATE TABLE Array_TEST ( c1 Array(String)) engine = Memory

元组Tuple

元组类型由1~n个元素组成,每个元素之间允许设置不同的数据类型,且彼此之间不要求兼容。元组同样支持类型推断,其推断依据仍然以最小存储代价为原则。与数组类似,元组也可以使用两种方式定义,常规方式tuple(T),或者简写方式(T)。

--常规定义方式SELECT tuple(1,'a',now()) AS x, toTypeName(x)┌─x─────────────────┬─toTypeName(tuple(1, 'a', now()))─┐│ (1,'a','2019-08-28 21:36:32') │ Tuple(UInt8, String, DateTime) │└───────────────────┴─────────────────────┘ --简写定义方式SELECT (1,'a',now()) AS x, toTypeName(x)┌─x─────────────────┬─toTypeName(tuple(1, 'a', now()))─┐│ (1,'a','2019-08-28 21:36:32') │ Tuple(UInt8, String, DateTime) │└───────────────────┴─────────────────────┘ --建表时元组类型定义CREATE TABLE Array_TEST ( c1 Array(String)) engine = Memory

枚举Enum

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

在定义枚举集合的时候,有几点需要注意。首先,Key和Value是不允许重复的,要保证唯一性。其次,Key和Value的值都不能为Null,但Key允许是空字符串。在写入枚举数据的时候,只会用到Key字符串部分。

数据在写入的过程中,会对照枚举集合项的内容逐一检查。如果Key字符串不在集合范围内则会抛出异常。

为什么还需要专门的枚举类型呢?这是出于性能的考虑。因为枚举定义中的Key属于String类型,但在后续对枚举的所有操作中(包括排序、分组、去重、过滤等),会使用Int类型的Value值。

--枚举类型定义CREATE TABLE Enum_TEST ( c1 Enum8('ready' = 1, 'start' = 2, 'success' = 3, 'error' = 4)) ENGINE = Memory; --枚举类型插入INSERT INTO Enum_TEST VALUES('ready');INSERT INTO Enum_TEST VALUES('start');

嵌套Nested

嵌套类型,顾名思义是一种嵌套表结构。一张数据表,可以定义任意多个嵌套类型字段,但每个字段的嵌套层级只支持一级,即嵌套表内不能继续使用嵌套类型。对于简单场景的层级关系或关联关系,使用嵌套类型也是一种不错的选择。

--创建Nested语句CREATE TABLE nested_test ( name String, age UInt8 , dept Nested( id UInt8, name String )) ENGINE = Memory;

ClickHouse的嵌套类型和传统的嵌套类型不相同,导致在初次接触它的时候会让人十分困惑。以上面这张表为例,如果按照它的字面意思来理解,会很容易理解成nested_test与dept是一对一的包含关系,其实这是错误的。

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

插入数据时候每一个nestd字段要需要一个数组。

--插入数据INSERT INTO nested_test VALUES ('bruce' , 30 , [10000,10001,10002], ['研发部','技术支持中心','测试部']);--行与行之间,数组长度无须对齐INSERT INTO nested_test VALUES ('bruce' , 30 , [10000,10001], ['研发部','技术支持中心']); --查询数据SELECT name, dept.id, dept.name FROM nested_test┌─name─┬─dept.id──┬─dept.name─────────────┐│ bruce │ [16,17,18] │ ['研发部','技术支持中心','测试部'] │└────┴───────┴────────────────────┘

特殊数据类型

Nullable

Nullable并不能算是一种独立的数据类型,它更像是一种辅助的修饰符,需要与基础数据类型一起搭配使用。Nullable类型与Java8的Optional对象有些相似,它表示某个基础数据类型可以是Null值。

CREATE TABLE Null_TEST ( c1 String, c2 Nullable(UInt8)) ENGINE = TinyLog;--通过Nullable修饰后c2字段可以被写入Null值:INSERT INTO Null_TEST VALUES ('nauu',null)INSERT INTO Null_TEST VALUES ('bruce',20)SELECT c1 , c2 ,toTypeName(c2) FROM Null_TEST┌─c1───┬───c2─┬─toTypeName(c2)─┐│ nauu │ NULL │ Nullable(UInt8) ││ bruce │ 20 │ Nullable(UInt8) │└─────┴──────┴───────────┘

Domain

域名类型分为IPv4和IPv6两类,本质上它们是对整型和字符串的进一步封装。IPv4类型是基于UInt32封装的。

ClickHouse相关资料分享

ClickHouse经典中文文档分享

ClickHouse(05)ClickHouse数据类型详解


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK