---
title: "ClickHouse 数据定义"
date: 2020-09-23T12:00:00+08:00
lastmod: 2020-09-23T12:00:00+08:00
tags: []
categories: ["clickhouse"]
---

## 基础类型
### 整数
声明   | 大小(字节) | 范围
----   | ----       | ----
Int8   | 1          | -128 到 127
UInt8  | 1          | 0 到 255
Int16  | 2          | -32768 到 32767
UInt16 | 2          | 0 到 65535
Int32  | 4          | -2147483648 到 2147483647
UInt32 | 4          | 0 到 4294967295
Int64  | 8          | -9223372036854775808 到 9223372036854775807
UInt64 | 8          | 0 到 18446744073709551615

### 浮点数
声明    | 大小(字节) | 有效精度(位数)
----    | ----       | ----
Float32 | 4          | 7
Float64 | 8          | 16

- 正无穷: SELECT 0.8/0
- 负无穷: SELECT -0.8/0
- 非数字: SELECT 0/0

### 定点数
- 原生声明: Decimal(P,S)
    - P: 总位数(整数+小数)，取值范围 1~38
    - S: 小数位数，取值范围 0~P

- 其他声明
    - Decimal32(S): -10^(9-S) 到 10^(9-S)
    - Decimal64(S): -10^(18-S) 到 10^(18-S)
    - Decimal128(S): -10^(18-S) 到 10^(38-S)

### 字符串
声明           | 备注
----           | ----
String         | 长度不固定，不限字符集，建议 UTF-8
FixedString(N) | 长度固定，null 字节填充
UUID           | 格式是 8-4-4-4-12，0 填充

### 时间
声明           | 精度 | 示例
----           | ---- | ----
Datetime       | 秒   | 2020-09-18 19:59:00
Datetime64(N)  | 亚秒 | 2020-09-18 19:59:00.00
Date           | 日   | 2020-09-18

## 复合类型
### 数组
- 声明: [T], Array(T)
- 查询时会以最小储存代价为原则推断类型
- 元素类型可以不同，但必须兼容

### 元组
- 声明: (T), tuple(T)
- 查询时会以最小储存代价为原则推断类型
- 元素类型可以不同，且无须兼容

### 枚举
声明                               | Key 类型 | Value 类型
----                               | ----     | ----
Enum8('k1'=1,'k2'=2, ... ,'kN'=N)  | String   | Int8
Enum16('k1'=1,'k2'=2, ... ,'kN'=N) | String   | Int16

- 枚举的所有后续操作，都会使用 Int 类型的 Value 值

### 嵌套
- 声明
    ```sql
    Nested(
        column1 T,
        column2 T
    )
    ```
- 嵌套字段中的每一列期望写入的是数组: Array(T)
- 同一行数据内，嵌套字段中的每一列的数组长度必须相等
- 访问嵌套字段中的列时用点(.)连接

### 可空类型
- 声明: Nullable(T)
- 只能和基础类型搭配使用，不用用于复合类型和索引字段
- 慎用，会额外生成 [Column].null.bin 文件保存 null 值，导致双倍文件操作，使查询和写入变慢

### 域名类型
声明 | 封装类型
---- | ----
IPv4 | UInt32
IPv6 | FixedString(16)

- Domain 类型不是字符串，不支持自动类型转换
- 调用 IPv4NumToString 或 IPv6NumToString 函数返回 IP 的字符串形式

## 数据库
### 操作
- 创建
    ```sql
    CREATE DATABASE [IF NOT EXISTS] db_name [ENGINE = engine];
    ```

- 查看数据库列表
    ```sql
    SHOW DATABASES;
    ```

- 切换
    ```sql
    USE db_name;
    ```

- 查看当前数据库中的数据表列表
    ```sql
    SHOW TABLES;
    ```

### 引擎
- Ordinary: 默认引擎，无须刻意声明，可以使用任意类型表引擎
- Dictionary: 字典引擎，自动为所有数据字典创建数据表
- Memory: 内存引擎，存放临时数据，数据只停留在内存中
- Lazy: 日志引擎，只能使用 Log 系列的表引擎
- MySQL: MySQL 引擎，自动拉取远端 MySQL 中的数据，并创建 MySQL 表引擎的数据表

## 数据表
### 操作
- 常规建表，默认在 default 数据库中创建
    ```sql
    CREATE TABLE [IF NOT EXISTS] [db_name.]table_name {
        column1 [type] [DEFAULT|MATERIALIZED|ALIAS expr],
        column1 [type] [DEFAULT|MATERIALIZED|ALIAS expr],
        ...
        columnM Nested(
            column11 [type],
            column22 [type],
            ...
        ),
        ...
    } ENGINE = engine;
    ```

- 复制其他表的结构
    ```sql
    CREATE TABLE [IF NOT EXISTS] [db_name.]table_name
        AS [db_name1.]table_name1
        [ENGINE = engine];
    ```

- 通过 SELECT 字句建表，顺带写入 SELECT 子查询的数据
    ```sql
    CREATE TABLE [IF NOT EXISTS] [db_name.]table_name
        ENGINE = engine
        AS SELECT ... ;
    ```

- 删表
    ```sql
    DROP TABLE [IF EXISTS] [db_name.]table_name;
    ```

- 增加表字段，默认值补全
    ```sql
    ALTER TABLE [db_name.]table_name ADD COLUMN [IF NOT EXISTS] 
        col_name [type] [default_expr] [AFTER col_name_after];
    ```

- 修改表字段
    ```sql
    ALTER TABLE [db_name.]table_name MODIFY COLUMN [IF EXISTS]
        col_name [type] [default_expr];
    ```

- 修改备注
    ```sql
    ALTER TABLE [db_name.]table_name COMMENT COLUMN [IF EXISTS]
        name 'some comment';
    ```

- 删除字段
    ```sql
    ALTER TABLE [db_name.]table_name DROP COLUMN [IF EXISTS] name;
    ```

- 移动数据表，只能在单节点内移动
    ```sql
    RENAME TABLE [db_name.]tb_name TO [db_name1.]tb_name1,
        [db_name2.]tb_name2 TO [db_name3.]tb_name3,
        ... ;
    ```

- 清空数据表
    ```sql
    TRUNCATE TABLE [IF EXISTS] [db_name.]tb_name;
    ```

### 表字段默认值
- 声明: DEFAULT、MATERIALIZED、ALIAS
- 如果表字段没有明确类型定义，则可根据默认值进行类型推断
- 写入数据时，只有 DEFAULT 类型字段可以 INSERT
- 查询数据时，只有 DEFUALT 类型字段可以 SELECT * 返回
- DEFAULT 和 MATERIALIZED 类型字段可以持久化

## 临时表
### 操作
- 创建
    ```sql
    CREATE TEMPORARY TABLE [IF NOT EXISTS] table_name {
        column1 [type] [DEFAULT|MATERIALIZED|ALIAS expr],
        column1 [type] [DEFAULT|MATERIALIZED|ALIAS expr],
        ...
        columnM Nested(
            column11 [type],
            column22 [type],
            ...
        ),
        ...
    };
    ```

### 其他
- 临时表只支持 Memory 表引擎，与会话绑定
- 临时表不属于任何数据库，创建时无数据库参数和表引擎参数
- 临时表优先级大于普通表

## 分区表
### 操作
- 创建
    ```sql
    CREATE TABLE partition_v1 (
        ID String,
        URL String,
        EventTime Date
    ) ENGINE = MergeTree()
    PARTITION BY toYYYYMMM(EventTime)
    GROUP BY ID;
    ```

- 查看分区状态
    ```sql
    SELECT table,partition,path from system.parts WHERE table = 'partition_v1'
    ```

- 删除分区
    ```sql
    ALTER TABLE tb_name DROP PARTITION part_expr;
    ```

- 复制分区，前提是两表的结构和分区键相同
    ```sql
    ALTER TABLE table_name1 REPLACE PARTITION part_expr FROM table_name;
    ```

- 重置分区数据
    ```sql
    ALTER TABLE table_name CLEAR COLUMN col_name IN PARTITION part_expr;
    ```

- 卸载分区
    ```sql
    ALTER TABLE table_name DETACH PARTITION part_expr;
    ```

- 装载分区
    ```sql
    ALTER TABLE table_name ATTACH PARTITION part_expr;
    ```

### 其他
- 分区支持删除、替换和重置，只有 MergeTree 系列表引擎支持

## 视图
### 操作
- 创建普通视图
    ```sql
    CREATE VIEW [IF NOT EXISTS] [db_name.]view_name AS SELECT ... ;
    ```

- 创建物化视图
    ```sql
    CREATE [MATERIALIZED] VIEW [IF NOT EXISTS] [db.]table_name
        [TO [db.]name] [ENGINE = engine] [POPULATE] AS SELECT ... ;
    # 如果使用了 POPULATE 修饰符，那么在创建视图时会一并导入 SELECT 结果集
    ```

- 查看物化视图列表
    ```sql
    SHOW TABLES
    # 输出前缀是 .inner.
    ```

- 删除视图
    ```sql
    DROP TABLE view_name
    ```

### 其他
- 普通视图只是查询代理
- 物化视图有独立存储，不支持同步删除

## 分布式 DDL
- 使用 ON CLUSTER cluster_name 声明语句
    ```sql
    CREATE TABLE table_name ON CLUSTER cluster_name(
        col1 [type],
        col2 [type],
        ...
    ) ENGINE = engine ... ;
    ```

## 写入数据
- INSERT 语句三种语法
    ```sql
    INSERT INTO [db_name.]table_name [(c1,c2,c3 ...)]
        VALUES (v1,v2,v3 ...), (v4,v5,v6 ...) ... ;

    INSERT INTO [db_name.]table_name [(c1,c2,c3 ...)]
        FORMAT format_name data_set;

    INSERT INTO [db_name.]table_name [(c1,c2,c3 ...)] SELECT ... ;
    ```

## 修改和删除数据
### 操作
- 删除
    ```sql
    ALTER TABLE [db_name.]table_name DELETE WHERE filter_expr;
    ```

- 修改
    ```sql
    ALTER TABLE [db_name.]table_name UPDATE col1 = expr1 [, ...]
        WHERE filter_expr;
    ```

### 其他
- mutation 操作很重，后台执行，语句提交后立即返回，不支持事务，不能回滚
- 通过 system.mutations 系统表查询进度

