4. ClickHouse 数据类型

在系统表中检查数据类型名称是否区分大小写

SELECT * from  system.data_type_families;

一、数值类型

1. 整型

固定长度的整型,包括有符号整型或无符号整型。ClickHouse 则直接使用 Int8、Int16、Int32 和Int64 指代 4 种大小的 Int 类型,其末尾的数字正好表明了占用字节的大小(8 位 = 1 字节)。

  • 整型范围(-2n-1~2n-1-1)
  • 无符号整型范围(0~2n-1)

2. 浮点型(存在精度损失问题)

  • Float32 - float
  • Float64 - double

建议尽可能以整型形式存储数据。例如,将固定精度的数字转换为整数值,如果时间用毫秒为单位表示,因为浮点型进行计算时可能引起四舍五入的误差

3. Decimal

ClickHouse 提供了 Decimal32、Decimal64 和 Decimal128 三种精度的定点数。

  • 简写方式有 Decimal32(S)、Decimal64(S)、Decimal128(S) 三种。

  • 原生方式为 Decimal(P,S),其中:P 代表精度,决定总位数(整数部分+小数部分),取值范围是 1 ~38;·S 代表规模,决定小数位数,取值范围是 0~P

使用场景: 一般金额字段、汇率、利率等字段为了保证小数点精度,都使用 Decimal 进行存储。

二、字符串类型

1. String

2. FixedString

与String 相比,极少会使用 FixedString,因为使用起来不是很方便。

3. UUID

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

CREATE TABLE test_uuid(
    `uid` UUID,
    `name` String
)
ENGINE=Memory;

INSERT INTO test_uuid
SELECT generateUUIDv4(), 'zss';

三、时间类型

1. Date

Date 类型不包含具体的时间信息,只精确到天,支持字符串形式写入

2. DateTime

DateTime 类型包含时、分、秒信息,精确到秒,支持字符串形式写入

3. DateTime64

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

四、复杂类型

1. Enum

  • Enum8 用 'String'=Int8 对描述。
  • Enum16 用 'String'=Int16 对描述。

在定义常量时经常会使用的数据类型,Enum 保存 'string' = integer 的对应关系。

CREATE TABLE test_enum
(
    id UInt8,
    color Enum8('RED'=1, 'GREEN'=2, 'BLUE'=3)
)ENGINE = Memory;

DESC test_enum;

INSERT INTO test_enum VALUES(1, 'RED'), (3,'GREEN');

-- 没有声明的值是不能插入
INSERT INTO test_enum VALUES(4, 'pink');

-- 节省存储空间,提升处理效率;底层存储 Int 类型,占用空间小
SELECT id, toInt32(color) FROM test_enum;
SELECT id, CAST(color,'Int8') FROM test_enum;

2. Array(T)

Array(T):由 T 类型元素组成的数组。

T 可以是任意类型,包含数组类型。但不推荐使用多维数组,ClickHouse 对多维数组的支持有限。例如,不能在 MergeTree 表中存储多维数组。

数组是强数据类型

--toTypeName 查看变量的数据类型
SELECT array(1,2,3) AS arr, toTypeName(arr);

CREATE TABLE test_array
(
    name String,
    hobby Array(String)
) ENGINE = Log;

INSERT INTO test_array VALUES('张三2', ['读书', '爬山', '散步']);
INSERT INTO test_array VALUES('李四2', ['read', 'hiking', 'dance']);
INSERT INTO test_array VALUES('王五2', array('吃', '睡', '喝',' 玩'));

-- clickhouse 会利用多核处理器将数据分块存储、计算
SELECT * FROM test_array;

-- 查询数组中的数据
SELECT *, hobby[1] FROM test_array;

-- 遍历数组中每个元素,给每个元素加上'abc'
SELECT arrayMap(e -> concat(e, 'abc'), hobby) FROM test_array;

3. Tuple 元组

可以存储任意的数据类型,在定义的时候声明数据类型和数据元素个数

CREATE TABLE test_tuple
(
    name String,
    info Tuple(String, String, UInt8)
)ENGINE=Memory;

INSERT INTO test_tuple VALUES
('zss', ('M', 'coder', 23)),
('lss', tuple('F', 'coder', 23));

SELECT * FROM test_tuple;

-- 通过下标查询 tuple 数据
SELECT name, info.1 AS sex, info.2, info.3 age FROM test_tuple;

4. Nested

Nested 是一种嵌套表结构。一张数据表,可以定义任意多个嵌套类型字段,但每个字段的嵌套层级只支持一级,即嵌套表内不能继续使用嵌套类型。

CREATE TABLE test_nested
(
    id Int8,
    name String,
    hobby Nested(
        hid Int8,
        h1 String,
        h2 String
    )
)ENGINE=Memory;

-- 查看表结构:
DESC test_nested;

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

-- 插入数据
INSERT INTO test_nested VALUES (1, 'zss', [1,2,3],['吃','喝','睡'],['eat','drink','sleep']);
INSERT INTO test_nested VALUES (2, 'lss', [1,2,3],['吃','喝','睡'],['eat','drink','sleep']);

-- 查询数据
SELECT * FROM test_nested;

-- 复杂查询数据
SELECT id, name, hobby.hid, hobby.h1, hobby.h1[1] FROM test_nested;

5. Domain

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

  • 出于便捷性的考量,例如 IPv4 类型支持格式检查,格式错误的 IP 数据是无法被写入的
  • 出于性能的考量,同样以 IPv4 为例,IPv4 使用 UInt32 存储,相比 String 更加紧凑,占用的空间更小,查询性能更快
  • Domain 类型并不是字符串,所以它不支持隐式的自动类型转换。如果需要返回 IP 的字符串形式,则需要显式调用 IPv4NumToString 或 IPv6NumToString 函数进行转换。
CREATE TABLE test_domain
(
    id Int8,
    ip IPv4
)ENGINE=Memory;

INSERT INTO test_domain VALUES(1, '192.168.133.1');
INSERT INTO test_domain VALUES(1, '192.168.133'); -- 插入数据时会进行数据的检查所以这行数据会报错

6. Boolean 和 Nullable

ck 中没 有 Boolean 类型, 使用 1 和 0 来代表 true 和 false

Nullable 某种数据类型允许为 null, 或者是没有给值的情况下模式是 NULL

参考