【ClickHouse 常用 SQL 语句整理】

本文整理 ClickHouse 日常开发中常用的 SQL 语法,适合作为速查手册或博客笔记。ClickHouse 是一款面向在线分析(OLAP)的列式数据库管理系统,擅长海量数据的快速聚合查询。

目录

  1. 连接与基础操作
  2. 建表与 MergeTree 引擎
  3. 数据插入
  4. SELECT 查询
  5. 聚合与分组
  6. JOIN 查询
  7. 数据更新与删除
  8. 表结构修改
  9. 物化视图
  10. 常用函数
  11. 查询性能优化
  12. 分布式表
  13. 总结## 1. 连接与基础操作
    命令行连接# 使用 clickhouse-client 连接
bash 复制代码
clickhouse-client --host=主机 --port=9000 --user=用户名 --password=密码

在容器内执行

bash 复制代码
docker exec -it clickhouse-server clickhouse-client --query "SELECT version()"
sql 复制代码
查看库与表
sql
-- 查看所有数据库
SHOW DATABASES;

-- 使用数据库
USE mydb;

-- 查看当前库所有表
SHOW TABLES;

-- 查看表结构
DESC my_table;

2. 建表与 MergeTree 引擎

ClickHouse 最核心的表引擎是 MergeTree,它按 ORDER BY 排序数据,形成稀疏主键索引,让查询能快速跳过无关数据块。

sql 复制代码
基本建表语法
sql
CREATE TABLE [IF NOT EXISTS] [db.]table_name
(
    column1 Type1,
    column2 Type2,
    ...
)
ENGINE = MergeTree()
PARTITION BY 分区表达式
ORDER BY 排序表达式
实际示例
sql
CREATE TABLE wikistat
(
    `time` DateTime,
    `project` String,
    `subproject` String,
    `path` String,
    `hits` UInt64
)
ENGINE = MergeTree
ORDER BY (time);
sql
CREATE TABLE uk_price_paid
(
    price UInt32,
    date Date,
    postcode1 LowCardinality(String),
    postcode2 LowCardinality(String),
    type Enum8('terraced' = 1, 'semi-detached' = 2, 'detached' = 3, 'flat' = 4),
    is_new UInt8,
    duration Enum8('freehold' = 1, 'leasehold' = 2),
    addr1 String,
    addr2 String,
    town LowCardinality(String),
    county LowCardinality(String)
)
ENGINE = MergeTree
PARTITION BY toYYYYMM(date)
ORDER BY (postcode1, postcode2, addr1, addr2);
LowCardinality(String) 用于唯一值较少的列,内部使用字典编码,可显著减少存储并提升分组过滤性能。
sql 复制代码
个关键子句
子句	作用
ORDER BY	每个分片内按物理顺序排序数据,决定主键。必需。
PARTITION BY	将数据拆分为分区,通常按日期范围。不同分区中的 parts 不会合并,实现快速分区裁剪。
PRIMARY KEY	默认与 ORDER BY 相同,稀疏索引基于它构建。
sql 复制代码
通过 SELECT 建表
sql
CREATE TABLE target_table
ENGINE = MergeTree()
ORDER BY id
AS SELECT * FROM source_table WHERE 1 = 0;
## 3. 数据插入
ClickHouse 推荐批量插入,每次插入应尽量包含较多行(如 100,000 行),以减少写入开销。
sql 复制代码
sql
-- 单行插入
INSERT INTO wikistat (time, project, subproject, path, hits)
VALUES ('2024-01-01 00:00:00', 'en', 'wikipedia', '/wiki/ClickHouse', 100);

-- 多行插入
INSERT INTO wikistat (time, project, subproject, path, hits)
VALUES
    ('2024-01-01 00:00:00', 'en', 'wikipedia', '/wiki/A', 10),
    ('2024-01-01 01:00:00', 'en', 'wikipedia', '/wiki/B', 20),
    ('2024-01-01 02:00:00', 'en', 'wikipedia', '/wiki/C', 30);
sql 复制代码
-- 从 SELECT 插入
INSERT INTO target_table
SELECT * FROM source_table WHERE date >= '2024-01-01';
sql
-- 异步插入(适合少量频繁写入)
INSERT INTO YourTable
SETTINGS async_insert=1, wait_for_async_insert=1
VALUES (...);

4. SELECT 查询

sql 复制代码
ClickHouse 的 SELECT 语法与标准 SQL 高度兼容,完整语法结构如下:

sql
SELECT [DISTINCT] expr_list
[FROM [db.]table | (subquery) | table_function]
[PREWHERE expr]
[WHERE expr]
[GROUP BY expr_list]
[HAVING expr]
[ORDER BY expr_list]
[LIMIT [n, ]m]
[SETTINGS ...]

基础查询

sql 复制代码
sql
-- 查询全部列
SELECT * FROM wikistat LIMIT 10;

-- 只查询需要的列(推荐)
SELECT time, project, hits FROM wikistat LIMIT 100;
sql 复制代码
-- 条件过滤
SELECT * FROM wikistat
WHERE project = 'en' AND hits > 1000
LIMIT 10;
时间分桶聚合
ClickHouse 内置丰富的时间函数,非常适合时序数据分析。
sql 复制代码
sql
-- 按天聚合
SELECT toDate(time) AS date, sum(hits) AS hits
FROM wikistat
GROUP BY ALL
ORDER BY date ASC
LIMIT 5;
sql 复制代码
sql
-- 按小时聚合
SELECT toStartOfHour(time) AS hour, sum(hits) AS hits
FROM wikistat
WHERE date(time) = '2015-07-01'
GROUP BY ALL
ORDER BY hour ASC
LIMIT 5;
sql 复制代码
sql
-- 自定义时间间隔(4小时)
SELECT toStartOfInterval(time, INTERVAL 4 HOUR) AS interval, sum(hits) AS hits
FROM wikistat
WHERE date(time) = '2015-07-01'
GROUP BY ALL
ORDER BY interval ASC
LIMIT 6;
sql 复制代码
动态列选择
sql
-- 使用正则匹配列名
SELECT COLUMNS('a') FROM col_names;

5. 聚合与分组

sql 复制代码
sql
-- 基础聚合
SELECT
    project,
    count() AS cnt,
    sum(hits) AS total_hits,
    avg(hits) AS avg_hits,
    max(hits) AS max_hits
FROM wikistat
GROUP BY project
ORDER BY total_hits DESC
LIMIT 10;
sql 复制代码
-- 带 HAVING 过滤
SELECT subproject, sum(hits) AS total
FROM wikistat
WHERE project = 'it'
GROUP BY subproject
HAVING total > 1000000
ORDER BY total DESC;

6. JOIN 查询

sql 复制代码
ClickHouse 支持标准 SQL JOIN,语法与 MySQL 类似。

sql
-- INNER JOIN
SELECT m.name AS movie_name, g.genre AS genre
FROM movies AS m
INNER JOIN genres AS g ON m.id = g.movie_id
ORDER BY m.year DESC
LIMIT 10;
sql 复制代码
sql
-- LEFT JOIN
SELECT u.name, o.order_no
FROM users u
LEFT JOIN orders o ON u.id = o.user_id;
sql
-- CROSS JOIN
SELECT * FROM t1 CROSS JOIN t2;

7. 数据更新与删除

ClickHouse 的 DELETE 和 UPDATE 与 MySQL 有本质区别。DELETE 语句在 ClickHouse 中是轻量级删除,底层通过为受影响的行应用"掩码"来实现,删除的行会立即被后续查询过滤掉,数据清理在后台异步进行。

sql 复制代码
sql
-- 轻量级删除(推荐)
DELETE FROM wikistat WHERE project = 'en' AND hits < 10;
sql
-- ALTER TABLE DELETE(Mutation 方式,会重写数据块)
ALTER TABLE wikistat DELETE WHERE hits < 10;
sql
-- 按分区删除(最高效)
ALTER TABLE wikistat DROP PARTITION '202401';
大规模删除会对 ClickHouse 性能产生负面影响。如果预计会频繁执行删除操作,建议考虑使用自定义分区键。

8. 表结构修改

sql 复制代码
sql
-- 添加列
ALTER TABLE events ADD COLUMN favoriteNumber Float64 DEFAULT 7;

-- 修改列类型
ALTER TABLE events MODIFY COLUMN favoriteNumber Int64;

-- 重命名列
ALTER TABLE events RENAME COLUMN old_name TO new_name;

-- 删除列
ALTER TABLE events DROP COLUMN favoriteNumber;

-- 添加列并指定位置
ALTER TABLE events ADD COLUMN new_col String AFTER existing_col;

9. 物化视图

物化视图是 ClickHouse 中用于预聚合和加速查询的重要工具。它会在数据插入源表时自动计算并写入目标表,查询时直接查目标表即可。

sql 复制代码
sql
-- 创建目标表
CREATE TABLE wikistat_top
(
    `path` String,
    `month` Date,
    hits UInt64
)
ENGINE = SummingMergeTree
ORDER BY (month, hits);

-- 创建物化视图
CREATE MATERIALIZED VIEW wikistat_top_mv
TO wikistat_top
AS
SELECT
    path,
    toStartOfMonth(time) AS month,
    sum(hits) AS hits
FROM wikistat
GROUP BY path, month;
使用物化视图后,原本需要 2.285 秒的查询可以降至毫秒级。

10. 常用函数

sql 复制代码
sql
-- 日期时间
SELECT now(), today(), yesterday();
SELECT toDate('2024-01-15 10:30:00');        -- 转为日期
SELECT toStartOfHour(now());                  -- 小时的开始
SELECT toStartOfDay(now());                   -- 天的开始
SELECT toYYYYMM(now());                       -- 年月数字

-- 字符串
SELECT length('hello');
SELECT substring('ClickHouse', 1, 5);
SELECT upper('hello'), lower('HELLO');
SELECT concat('a', 'b', 'c');
SELECT replace('hello world', 'world', 'ClickHouse');

-- 类型转换
SELECT toString(123);
SELECT toUInt32('456');
SELECT toFloat64('3.14');

-- 聚合
SELECT count(), uniq(project), uniqExact(project) FROM wikistat;
SELECT groupArray(project) FROM wikistat LIMIT 5;
SELECT quantile(0.5)(hits) FROM wikistat;    -- 中位数

-- 条件
SELECT if(hits > 1000, 'high', 'low') FROM wikistat;
SELECT multiIf(hits > 10000, 'A', hits > 1000, 'B', 'C') FROM wikistat;

-- 空值处理
SELECT ifNull(nullable_col, 'default') FROM my_table;
SELECT coalesce(col1, col2, 'fallback') FROM my_table;

11. 查询性能优化

sql 复制代码
核心原则
优化 ORDER BY 键是首要任务,因为它决定了主键索引,直接影响数据裁剪效率。

优化前后对比(查询 WHERE project = 'it'):

查询	ORDER BY (time)	ORDER BY (project, subproject, time)
按 project 分组	2.381 秒	1.660 秒
按 subproject 分组	2.148 秒	0.058 秒
按月份分组	2.192 秒	0.012 秒

优化建议
不要使用 SELECT *,只查询需要的字段。ClickHouse 按需读取列,SELECT * 会读取所有列,增加不必要的 IO。

使用 PREWHERE 替代 WHERE,优先过滤数据,加速查询。

通过 LIMIT 限制返回数据量,节省计算资源和网络开销。

使用物化视图预聚合常用查询结果。

避免 Nullable 列,使用默认值代替,减少存储开销并提升查询性能。

sql
-- PREWHERE 示例:先过滤再读取其他列
SELECT project, sum(hits)
FROM wikistat
PREWHERE project = 'it'
WHERE hits > 100
GROUP BY project;
查看执行计划
sql
EXPLAIN SELECT * FROM wikistat WHERE project = 'en';

12. 分布式表

sql 复制代码
在 ClickHouse 集群中,通常先创建本地表,再基于本地表创建分布式表。

sql
-- 1. 创建本地表(每个分片各有一份)
CREATE TABLE my_table_local ON CLUSTER my_cluster
(
    id UInt64,
    name String,
    value Float64
)
ENGINE = MergeTree()
ORDER BY id;

-- 2. 创建分布式表(统一查询入口)
CREATE TABLE my_table_all ON CLUSTER my_cluster
AS my_table_local
ENGINE = Distributed(my_cluster, my_db, my_table_local, rand());
sql
-- 通过分布式表写入和查询
INSERT INTO my_table_all VALUES (1, 'a', 1.0), (2, 'b', 2.0);

SELECT * FROM my_table_all WHERE value > 1;

13. 总结

sql 复制代码
本文整理了 ClickHouse 日常开发中的常用 SQL 语法,涵盖:

库表基础操作

MergeTree 建表与引擎选择

批量数据插入

SELECT 查询与时间分桶聚合

JOIN、聚合、分组

轻量级删除与表结构修改

物化视图加速查询

常用内置函数

查询性能优化核心原则

分布式表创建

与 MySQL 不同,ClickHouse 是列式数据库,更适合 OLAP 场景下的聚合分析查询。使用时应充分利用 ORDER BY 排序键、PARTITION BY 分区裁剪和物化视图来提升查询性能。
相关推荐
想念是会呼吸的鱼2 小时前
MySQL 常用语法整理
sql·mysql
SelectDB技术团队3 小时前
StarRocks 迁移至 Apache Doris 完整指南:三步完成结构、数据与业务平滑切换
数据库·人工智能·sql·clickhouse·apache doris·selectdb·湖仓架构升级
imDwAaY4 小时前
MySQL MVCC 详解:原理、版本链、Read View 与可见性判断
数据库·sql·mysql
bbq粉刷匠17 小时前
触发器(下):事务与锁、binlog 一致性与替代方案
sql
浅念-19 小时前
Redis基础详解:单线程模型、String与Hash数据结构
服务器·数据库·redis·sql·mysql·nosql数据库·nosql
databook1 天前
使用 DuckDB 分析 Parquet 文件
sql·数据分析·nosql
旺仔不是程序员1 天前
相关子查询与性能优化:PostgreSQL 逐行执行的代价与 JOIN 重写
数据库·后端·sql
绘梨衣5471 天前
慢SQL排查手册
python·sql