ClickHouse SQL 极简教程ClickHouse SQL之数据定义语言 DDL

Posted 东海陈光剑

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ClickHouse SQL 极简教程ClickHouse SQL之数据定义语言 DDL相关的知识,希望对你有一定的参考价值。

1.1. ClickHouse SQL之数据定义语言 DDL 

本节介绍 ClickHouse 中进行数据库、表结构的定义和管理。

1.1.1. 概述

在SQL中,数据定义语言( DDL ) 用来创建和修改数据库Schema,例如表、索引和用户等。其中数据库的Schema描述了用户数据模型、字段和数据类型。DDL 语句类似于用于定义数据结构的计算机编程语言。常见DDL 语句包括CREATE、ALTER、DROP等。

ClickHouse SQL中的DDL,除了可以定义数据库、表、索引和视图等之外,还可以定义函数和字典等。

1.1.2. 创建数据库

语法

CREATE DATABASE [IF NOT EXISTS] db_name

[ON CLUSTER cluster]

[ENGINE = db_engine(...)]

[COMMENT 'Comment']

功能说明

1. 创建名称为db_name的数据库。

2. 如果指定了 ON CLUSTER cluster 子句,那么在指定集群 cluster 的所有服务器上创建 db_name 数据库。

3. ENGINE = db_engine(...), 数据库引擎。ClickHouse 默认使用 Atomic 数据库引擎,即有默认值 ENGINE = Atomic。Atomic 引擎提供了可配置的 table engines 和 SQL dialect,它支持非阻塞的DROP TABLE和RENAME TABLE查询和原子的表交换查询命令 EXCHANGE TABLES t1 AND t2。Atomic 中的所有表都有持久的 UUID,数据存储在/clickhouse_path/store/xxx/xxxyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy/ 路径下。其中,xxxyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy是表 UUID,支持在不更改 UUID 和移动表数据的情况下执行重命名。可以使用DatabaseCatalog,通过 UUID访问 Atomic 数据库中的表。执行DROP TABLE 命令,不会删除任何数据,Atomic 数据库只是通过将元数据移动到 /clickhouse_path/metadata_dropped/,并将表标记为已删除,并通知 DatabaseCatalog。

在 20.5 版本中(可以使用 SELECT version() 查看 ClickHouse 版本),ClickHouse 首次引入了数据库引擎 Atomic。从 20.10 版开始,它是默认数据库引擎(之前默认使用 engine=Ordinary )。SQL 如下:

SELECT version()

Query id: 45ca90b4-5e17-4106-a92f-f8fed8822286

┌─version()────┐

│ 21.12.1.8808 │

└──────────────┘

SHOW CREATE DATABASE system

FORMAT TSVRaw

Query id: 19d3e06d-dfaf-45b4-a67d-156199098bc4

CREATE DATABASE system

ENGINE = Atomic

这两个数据库引擎在文件系统上存储数据的方式有所不同(Ordinary引擎的文件系统布局更简单),Atomic 引擎解决了Ordinary引擎中存在的一些问题。

Atomic 引擎支持非阻塞删除表/重命名表、异步表删除和分离(delete&detach)(等待查询完成,但对新查询不可见)、原子删除表(删除所有文件/文件夹)、原子表交换(通过“EXCHANGE TABLES t1 AND t2”进行表交换)、重命名字典/重命名数据库、

在FS和ZK 中自动生成唯一UUID 路径用于复制。ClickHouse 支持的数据库引擎可以在 源码目录 src/Databases 下面找到。例如在DatabaseFactory.cpp(112行)中,可以看到 ClickHouse数据库引擎集合:

database_engines "Ordinary", "Atomic", "Memory","Dictionary", "Lazy", "Replicated", "mysql", "MaterializeMySQL", "MaterializedMySQL", "PostgreSQL", "MaterializedPostgreSQL","SQLite"

4. COMMENT 'Comment',添加数据库注释。所有数据库引擎都支持该注释。

Ø 数据库引擎Atomic与Ordinary对比

数据库引擎

Ordinary

Atomic

文件系统布局

简单

复杂

外部工具支持,如 clickhouse-backup等

好/成熟

有限/测试版

一些 DDL 查询(DROP / RENAME)可能要挂起等待很长时间

是的

没有

支持交换 2 张表操作

renamea to a_old,b to a,a_old to b;操作不是原子的,并且 可以在中间突破(虽然机会很低)。

EXCHANGE TABLES t1 AND t2;原子操作,没有中间状态。

使用 zookeeper路径中的 uuid

无法使用。典型的模式是需要创建同一张表的新版本的时候,给zookeeper路径加上版本后缀。

可以在 zookeeper 路径中使用 uuid。可以在 zookeeper 路径中使用 uuid。但是,当扩展集群时,这需要格外小心。Zookeeper 路径更难以映射到真实表。允许对表进行任何类型的操作(重命名、使用相同名称重新创建等)。

物化视图,建议始终使用 TO 语法。

.inner.mv_name, 名字可读。

.inner_id.uuid,名字不可读。

创建一个使用 Atomic引擎的数据库

CREATE DATABASE if not exists clickhouse_tutorial ENGINE = Atomic;

查看数据库列表

使用命令show databases 可以看到数据库列表如下。

SHOW DATABASES

Query id: 08c13dfb-0f5c-4aea-815a-68ec95eaa037

┌─name────────────────┐

│ INFORMATION_SCHEMA  │

│ clickhouse_tutorial │

│ default             │

│ information_schema  │

│ mydb                │

│ system              │

│ tutorial            │

└─────────────────────┘

如果想要看当前ClickHouse Server 进程实例下更加详细的数据库列表信息,可以使用 select * from system.databases 命令。为了可读性,输出结果整理成表格如下。

name

engine

data_path

metadata_path

uuid

comment

database

INFORMATION_SCHEMA

Memory

./


00000000-0000-0000-0000-000000000000



clickhouse_tutorial

Atomic

./store/

/Users/chenguangjian/store/3c0/3c0b76c0-1dac-4f88-bc0b-76c01dac3f88/

3c0b76c0-1dac-4f88-bc0b-76c01dac3f88



default

Atomic

./store/

/Users/chenguangjian/store/d62/d62015e0-b943-4090-9620-15e0b9432090/

d62015e0-b943-4090-9620-15e0b9432090



information_schema

Memory

./


00000000-0000-0000-0000-000000000000



mydb

Ordinary

./data/mydb/

/Users/chenguangjian/metadata/mydb/

00000000-0000-0000-0000-000000000000

mydb


system

Atomic

./store/

/Users/chenguangjian/store/268/2682f921-c33f-4278-a682-f921c33f9278/

2682f921-c33f-4278-a682-f921c33f9278



tutorial

Atomic

./store/

/Users/chenguangjian/store/d34/d34824fa-e714-43e8-9348-24fae71403e8/

d34824fa-e714-43e8-9348-24fae71403e8



可以看出,使用Atomic引擎的元数据路径上都带有 UUID,而使用Ordinary引擎的路径使用的是数据库名字,Memory引擎则没有元数据存储到磁盘文件上。

可以使用命令show create database system 查看system 数据库建库命令:

CREATE DATABASE system

ENGINE = Atomic

可见,system使用的是Atomic引擎。

1.1.3. 删除数据库

使用 DROP命令删除数据库,SQL实例如下:

drop DATABASE if exists clickhouse_tutorial;

使用 select * from system.databases 查看数据库列表里面,clickhouse_tutorial已经被删掉。

1.1.4. 创建MergeTree表 

语法

ClickHouse 中最强大的表引擎是*MergeTree家族系列,也是使用最多的表引擎。

创建MergeTree表SQL语法如下:

CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster_name]

(

    name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1] [TTL expr1],

    name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2] [TTL expr2],

    ...

    INDEX index_name1 expr1 TYPE type1(...) GRANULARITY value1,

    INDEX index_name2 expr2 TYPE type2(...) GRANULARITY value2,

    ...

    PROJECTION projection_name_1 (SELECT <COLUMN LIST EXPR> [GROUP BY] [ORDER BY]),

    PROJECTION projection_name_2 (SELECT <COLUMN LIST EXPR> [GROUP BY] [ORDER BY])

) ENGINE = MergeTree()

ORDER BY expr

[PARTITION BY expr]

[PRIMARY KEY expr]

[SAMPLE BY expr]

[TTL expr

    [DELETE|TO DISK 'xxx'|TO VOLUME 'xxx' [, ...] ]

    [WHERE conditions]

    [GROUP BY key_expr [SET v1 = aggr_func(v1) [, v2 = aggr_func(v2) ...]] ] ]

[SETTINGS name=value, ...]

功能说明

1. ON CLUSTER cluster_name,在ClickHouse集群cluster_name上建表。默认情况下,表仅在当前服务器上创建。如果是在ClickHouse集群cluster_name的所有服务节点上建表,使用分布式 DDL 查询子句 ON CLUSTER 实现。

2. ENGINE = table_engine,指定表引擎。可以通过SQL查询system.table_engines表内容,获得ClickHouse支持的表引擎。如下所示。

SELECT

    name,

    supports_ttl

FROM system.table_engines

Query id: f219cd4d-dd2b-4490-a9aa-e66f29cec9ac

┌─name───────────────────────────────────┬─supports_ttl─┐

│ PostgreSQL                             │            0 │

│ RabbitMQ                               │            0 │

│ Kafka                                  │            0 │

│ S3                                     │            0 │

│ ExecutablePool                         │            0 │

│ MaterializedView                       │            0 │

│ MaterializedPostgreSQL                 │            0 │

│ EmbeddedRocksDB                        │            0 │

│ View                                   │            0 │

│ JDBC                                   │            0 │

│ Join                                   │            0 │

│ ExternalDistributed                    │            0 │

│ Executable                             │            0 │

│ Set                                    │            0 │

│ Dictionary                             │            0 │

│ GenerateRandom                         │            0 │

│ LiveView                               │            0 │

│ MergeTree                              │            1 │

│ Memory                                 │            0 │

│ Buffer                                 │            0 │

│ MongoDB                                │            0 │

│ URL                                    │            0 │

│ ReplicatedVersionedCollapsingMergeTree │            1 │

│ ReplacingMergeTree                     │            1 │

│ ReplicatedSummingMergeTree             │            1 │

│ COSN                                   │            0 │

│ ReplicatedAggregatingMergeTree         │            1 │

│ ReplicatedCollapsingMergeTree          │            1 │

│ File                                   │            0 │

│ ReplicatedGraphiteMergeTree            │            1 │

│ ReplicatedMergeTree                    │            1 │

│ ReplicatedReplacingMergeTree           │            1 │

│ VersionedCollapsingMergeTree           │            1 │

│ SummingMergeTree                       │            1 │

│ Distributed                            │            0 │

│ TinyLog                                │            0 │

│ GraphiteMergeTree                      │            1 │

│ SQLite                                 │            0 │

│ CollapsingMergeTree                    │            1 │

│ Merge                                  │            0 │

│ AggregatingMergeTree                   │            1 │

│ ODBC                                   │            0 │

│ Null                                   │            0 │

│ StripeLog                              │            0 │

│ Log                                    │            0 │

└────────────────────────────────────────┴──────────────┘

45 rows in set. Elapsed: 0.001 sec.

3. (name1 [type1] , ... ),指定表字段名和字段数据类型。

4. NULL|NOT NULL,字段是否可空。

5. DEFAULT,指定字段默认值。字段可以通过表达式 DEFAULT expr指定默认值。如果 INSERT 查询没有指定对应的列,则通过计算对应的表达式来填充。例如:`URLDomain String DEFAULT domain(URL)`。如果未定义默认值的表达式,则默认值将设置为数字为零,字符串为空字符串,数组为空数组,日期为 1970-01-01,DateTime unix时间戳为零,NULL为空。

6. MATERIALIZED,物化字段列。这样的字段不能在 INSERT 语句中指定值插入,因为这样的字段总是通过使用其他字段计算出来的。

7. EPHEMERAL,临时字段列。这样的列不存储在表中,不能被SELECT 查询,但可以在 CREATE 语句的默认值中引用。

8. ALIAS,字段别名。该别名值不会存储在表中,SELECT 查询中使用星号时不会被替换。如果在查询解析期间扩展了别名,则可以在 SELECT 中使用它。

9. INDEX index_name1 expr1 TYPE type1(...) GRANULARITY value1,指定索引字段和索引粒度。

10. PROJECTION projection_name_1,指定物化投影字段创建一个 Projection,为当前字段Where查询加速。Projection 思想源自 《C-Store: A Column-oriented DBMS》这篇论文,作者是2015年图灵奖获得者、Vertica 之父,Mike Stonebraker。Projection 意指一组列的组合,可以按照与原表不同的排序存储,并且支持聚合函数的查询。相当于传统意义上的物化视图,用空间换时间。它借鉴 MOLAP 预聚合的思想,在数据写入的时候,根据 PROJECTION定义的表达式,计算写入数据的聚合数据同原始数据一并写入。数据查询的过程中,如果查询SQL通过分析可以通过聚合数据得出,直接查询聚合数据减少计算的开销,解决了由于数据量导致的内存问题。Projection主要分为两种:normal与aggregate。相关源码参阅MergeTreeDataWriter.cpp(574 行)MergeTreeDataWriter::TemporaryPart MergeTreeDataWriter::writeProjectionPart()。

11. ORDER BY expr,指定排序字段元组,也即索引列(ClickHouse中的索引列即排序列)。从左到右顺序,建立稀疏索引组合键。合理设计排序键,对查询性能会有很大提升。一般选择查询条件中,筛选条件频繁的列。可以是单一维度,也可以是组合维度的索引。另外,基数特别大的不适合做索引列,如用户标签表的user_id字段。通常筛选后的数据量在百万级别,性能表现较好。

12. PARTITION BY expr,指定分区字段元组。分区字段数据存储到独立的文件夹目录下。

13. SAMPLE BY expr,指定采样字段。

14. compression_codec,指定压缩算法。通用编解码器有NONE(无压缩)、LZ4、LZ4HC、ZSTD。ClickHouse 默认使用 LZ4压缩算法CODEC(LZ4)。专用编解码器有Delta(delta_bytes)、DoubleDelta(适用于时间序列数据)、Gorilla、T64等。另外,使用CODEC('AES-128-GCM-SIV')、CODEC('AES-256-GCM-SIV')等可以加密磁盘上的数据。

15. TTL expr,表数据存活时间表达式。到期数据ClickHouse 会自动清理,对于数据 Part移动或重新压缩,数据的所有行都必须满足“TTL”表达式条件。只能为 MergeTree 系列表指定。TTL 子句不能用于主键列。例如,根据 date字段判断哪些数据到期, TTL表达式为:TTL date + INTERVAL 7 DAY,其中 date 为日期字段。那么,date=20220301的数据将会在 7 天后,也就是 20220308 零点日期被清理。

16. PRIMARY KEY,索引主键。

17. SETTINGS name=value, ...,指定配置项name=value,多个配置项之间用逗号分隔。例如,指定表的索引粒度:SETTINGS index_granularity = 8192。

实例讲解

创建MergeTree表

create table if not exists clickhouse_tutorial.user_tag

(

    user_id      UInt64 DEFAULT 0,

    gender       String DEFAULT 'NA',

    age          String DEFAULT 'NA',

    active_level String DEFAULT 'NA',

    date         Date

) engine = MergeTree()

      order by (user_id, active_level)

      primary key (user_id)

      partition by (date);

使用 show create table clickhouse_tutorial.user_tag 命令查询建表 SQL,执行结果如下:

SHOW CREATE TABLE clickhouse_tutorial.user_tag

FORMAT TSVRaw

Query id: 30ec8e45-8ead-419e-b8fc-dbce54b5939c

CREATE TABLE clickhouse_tutorial.user_tag

(

    `user_id` UInt64 DEFAULT 0,

    `gender` String DEFAULT 'NA',

    `age` String DEFAULT 'NA',

    `active_level` String DEFAULT 'NA',

    `date` Date

)

ENGINE = MergeTree

PARTITION BY date

PRIMARY KEY user_id

ORDER BY (user_id, active_level)

SETTINGS index_granularity = 8192

1 rows in set. Elapsed: 0.001 sec.

其中,index_granularity = 8192是默认的稀疏索引间隔行数。

使用PROJECTION创建MergeTree 表

使用PROJECTION语句建表:

create table if not exists clickhouse_tutorial.user_tag

以上是关于ClickHouse SQL 极简教程ClickHouse SQL之数据定义语言 DDL的主要内容,如果未能解决你的问题,请参考以下文章

ClickHouse SQL 语法极简教程

ClickHouse SQL 极简教程ClickHouse SQL之数据定义语言 DDL

ClickHouse SQL 极简教程ClickHouse SQL 之数据控制语言 DCL

ClickHouse SQL 极简教程ClickHouse SQL 之数据查询语言 DQL

ClickHouse SQL 极简教程使用EXPLAIN 分析 SQL 执行计划

ClickHouse SQL 语法基础极简教程 + bitmap 位图数据类型的使用实例