GaussDB SQL 调优
下载地址
https://www.zhengdianxue.com/wp-content/uploads/skills/org-e3rjs5bu--gaussdb-sql-tuning.zip将提示词发送给你的 AI 安装该 skills
请根据 https://skillhub.cn/install/skillhub.md,安装 @org-e3rjs5bu/gaussdb-sql-tuning。华为 GaussDB / GaussDB(DWS) 的 MPP SQL 编写与调优。覆盖分布列、执行计划、数据倾斜和常见 SQL 改写。适用于 DISTRIBUTE BY、STREAM、FQS、EXPLAIN PERFORMANCE、列存与复制表等问题。 Use when writing, reviewing, explaining, or tuning Huawei GaussDB / GaussDB(DWS) SQL. Trigger on DISTRIBUTE BY, 分布列, 数据倾斜, CN/DN/GTM, STREAM, FQS, LIGHT_PROXY, REMOTE_QUERY, 列存, 复制表, EXPLAIN PERFORMANCE, or MPP join/group-by performance issues.
阅读全文 (展开查看完整说明)
概述
GaussDB(DWS) 是 MPP 库。性能首先由数据落在哪个 DN、查询会不会跨 DN 搬数据决定,不是由单机 PostgreSQL 习惯决定。
本技能基线:GaussDB 8.1.3(兼容 PostgreSQL 9.2.4 语法,但执行模型不是单机 PG)。
何时使用
- 写/改
CREATE TABLE、临时表、JOIN、GROUP BY、UNION、去重、EXISTS - 查询被杀、单 DN 打满、倾斜率高、跑十几分钟以上
- 需要解释 CN / DN / GTM、四种分布式计划、三种 Stream
不要用本技能处理:单机 MySQL/Oracle 语法、应用层事务设计、集群安装运维。
调优收益顺序
分布列 > 索引 > 普通 SQL 改写 > 业务拆批 > 硬件
先改分布,再改 SQL。只改 SELECT 列表解决不了倾斜。
写任何表之前
每张表必须显式写分布策略。不写时 GaussDB 默认用第一列 做 HASH 分布列,这是常见事故源。
CREATE LOCAL TEMPORARY TABLE tmp_x
WITH (ORIENTATION=COLUMN)
ON COMMIT PRESERVE ROWS
DISTRIBUTE BY HASH(join_or_group_key)
AS
SELECT ...;| 场景 | 分布 |
|---|---|
| 两表按某键 JOIN | 两表都 DISTRIBUTE BY HASH(该键) |
| 查询主要按某键 GROUP BY | HASH(该分组键) |
| 维表/码表,能放进各 DN | DISTRIBUTE BY REPLICATION |
| 业务键严重倾斜(如头部客户) | 随机键,或只对热点键加盐 |
| 未指定 | 禁止上线 |
详细判定与 SQL:references/distribute-keys.md
四种执行计划(好 → 差)
- CN 轻量化 / LIGHT_PROXY:谓词命中分布列,单 DN 执行。
- FQS / REMOTE_FQS_QUERY:各 DN 独立算完,CN 只汇总,DN 之间无交换。
- STREAM:DN 之间广播 / 聚集 / 重分布。复杂 JOIN、跨分布列聚合走这里。可接受,但要控制重分布量。
- Remote-Query / REMOTE_QUERY:DN 把中间结果送回 CN,CN 做大部分计算。极差。CTE + 后续复杂 JOIN 容易掉进这一档。
目标:让语句落在 1 或 2;需要 3 时让 JOIN/GROUP 键等于分布列;出现 4 就拆临时表或改写。
架构与 Stream:references/architecture.md
SQL 改写速查
| 不要 | 改成 |
|---|---|
UNION | UNION ALL + 外层 GROUP BY 去重 |
COUNT(DISTINCT x) | 先 GROUP BY 业务键,再 COUNT(*) |
NOT IN (SELECT ...) | NOT EXISTS |
IN (SELECT 大表) | EXISTS |
| 同一表达式写 3 遍 | CTE 或临时表算一次 |
SELECT * | 只要用到的列 |
HAVING 做行过滤 | WHERE |
'%keyword%' / WHERE func(col)= | 右模糊 'keyword%',不对索引列套函数 |
| 大表直接 JOIN 后再过滤 | 单表先过滤再 JOIN |
| 一次打全量超大 JOIN | HASHTEXT(key) % N 分批,同一 key 进同一批 |
完整正反例:references/sql-patterns.md
列存补充
分析型临时表默认列存:WITH (ORIENTATION=COLUMN)。
局部聚簇 PARTIAL CLUSTER KEY 只服务列存范围扫描(col op 常量),一般不超过 2 列。高过滤列、枚举列靠前。
范围/列表分区用于按时间淘汰历史数据,以及谓词能裁剪分区的查询。List 分区需要 8.1.3+。
诊断
用 EXPLAIN PERFORMANCE,不要只看 EXPLAIN。
判定倾斜:各 DN 数据量或耗时相差 > 10%。
常见杀查询信号(持续约 10 分钟):
- 单 DN 内存 > 15GB
- SQL 总 CPU 时间过大(量级 20 亿毫秒)
- 倾斜率 > 95%
- 执行超过 60 分钟
报表/智数类平台:必须显式 LIMIT(有的平台默认一次拉 1000 万行);资源窗口通常是晚上优于午休,午休优于下午,上午最挤。这是平台经验,以现场队列为准。
诊断步骤:references/diagnose.md
交付检查
写完 SQL 后按顺序回答,缺一项就改:
- 每张表是否都有
DISTRIBUTE BY? - JOIN / GROUP BY 键是否等于分布列,或小表已复制?
- 计划会不会变成 Remote-Query?
- 热点业务键有没有倾斜预案(随机 / 加盐 / 分批)?
- 是否还在用
UNION、COUNT(DISTINCT)、NOT IN、SELECT *? - 大结果集是否有
LIMIT或分批?
常见借口
| 借口 | 事实 |
|---|---|
| 这就是 PostgreSQL | 语法像 PG 9.2,执行是 MPP。不写分布列等于把第一列当 shard key。 |
| 优化器会自己推下去 | Remote-Query 和错误分布列不会被优化器救回来。 |
| 先跑通再调分布 | 分布列决定数据落点;事后改表成本高于一开始写对。 |
| 小表不用管 | 小表不复制就会广播或重分布。 |
| DISTINCT 更短 | 短查询不等于便宜。去重是排序/哈希全量。 |