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之数据定义语言 DDL
ClickHouse SQL 极简教程ClickHouse SQL 之数据控制语言 DCL
ClickHouse SQL 极简教程ClickHouse SQL 之数据查询语言 DQL