GaussDB数据库性能调优
2 GaussDB数据库性能调优
2.1 总结
本文档围绕 GaussDB 数据库性能调优展开,核心涵盖系统级指标及性能调优、WDR 报告详解、SQL 优化三大模块:系统级指标通过三级指标体系(系统级:OS/CPU/ 内存 / 会话,对象级:库 / 表 / 索引 / 锁,应用级:事务 / SQL / 慢查询)及dbe_perf系列视图实现瓶颈定位;WDR 报告作为性能 “体检报告”,通过定时快照(默认 60 分钟)采集性能数据,生成包含 Summary(负载 / CPU/IO)和 Detail(SQL 统计 / 等待事件)的报告,支持集群 / 节点级分析;SQL 优化则基于SQL 执行机制(解析→优化→执行),通过算子控制(扫描 / 关联 / 物化算子)、调优工具(work_mem参数、Plan Hint)及业务适配(交易类 CN 轻量化、混合负载类 SMP/RLBT),解决数据倾斜、计划选择不当等问题,最终实现数据库整体性能提升。
2.2 思维导图(mindmap)

2.3 详细总结
一、系统级指标及性能调优
1. 三级指标体系(核心内容)
|
指标层级 |
核心监控项 |
关键视图 / 工具 |
用途 |
|
系统级 |
OS(CPU 核数 / LOAD / 内存使用率) |
dbe_perf.os_runtime |
判断操作系统负载是否过高 |
|
|
Instance Time(DB_TIME/CPU_TIME/IO_TIME) |
dbe_perf.instance_time |
定位系统瓶颈(CPU/IO/ 网络) |
|
|
Memory(共享内存 / 会话内存使用) |
dbe_perf.shared_memory_detail、dbe_perf.session_memory_detail |
排查内存泄漏 / 过度使用 |
|
|
Session(活跃会话 / 等待事件) |
dbe_perf.session_stat_activity |
分析会话阻塞 / 慢查询根源 |
|
|
Event(IO/LOCK/LWLOCK/STATUS 等待) |
dbe_perf.wait_events |
定位细粒度时延问题(如 IO 等待过久) |
|
对象级 |
Database(连接数 / 事务提交数 / 物理读) |
dbe_perf.stat_database |
识别热点数据库,建立访存模型 |
|
|
Table(顺序 / 索引扫描次数、行增删改) |
dbe_perf.stat_user_tables、dbe_perf.statio_user_tables |
定位热点表,分析缓存命中率 |
|
|
Index(索引扫描次数 / 缓存命中) |
dbe_perf.stat_user_indexes、dbe_perf.statio_user_indexes |
评估索引收益,删除无效索引 |
|
|
Lock(锁等待关系 / 锁类型) |
dbe_perf.locks |
识别热点锁,解决事务阻塞 |
|
应用级 |
Statement(SQL 执行时间 / 行活动 / 排序溢出) |
dbe_perf.statements |
定位热点 SQL,分析性能瓶颈(如排序下盘) |
|
|
Active Session Profile(ASP) |
gs_asp |
低成本复现历史系统活动(默认 10 秒采样) |
|
|
Full SQL trace |
三级日志(L0:基础信息,L1:执行计划,L2:锁时间) |
精准定位 SQL 执行各阶段耗时 |
2. 性能瓶颈定位案例
案例 1:索引不当:某 SQL 时延 1.2s,通过dbe_perf.stat_user_indexes发现无匹配索引,重建复合索引后时延降至 100ms 内;
案例 2:集群性能不达标:通过dbe_perf.wait_events发现某 DN 等待DoubleWriteFileWrite事件,排查为备机 IO 瓶颈,更换存储后性能恢复;
案例 3:应用版本问题:Benchmark 事务成功率抖动,通过dbe_perf.instance_time发现NET_SEND_TIME异常,升级应用版本后网络开销降低 50%。
二、WDR 报告详解
1. WDR 基础配置
|
参数名称 |
功能 |
默认值 |
取值范围 |
|
enable_wdr_snapshot |
开启 / 关闭快照功能 |
off |
on/off |
|
wdr_snapshot_interval |
快照采集周期 |
60 分钟 |
10 分钟~1 天 |
|
wdr_snapshot_retention_days |
快照保留时间 |
8 天 |
1~30 天 |
|
create_wdr_snapshot() |
手动生成快照 |
- |
无 |
2. 报告生成与限制
生成步骤:
gsql 连接 postgres 库;
执行\a \t \o /path/cluster.html(指定输出路径);
调用函数:select generate_wdr_report(begin_snap_id, end_snap_id, 'all', 'cluster', '');
限制条件:
快照间不可有节点重启、Drop Database、主备倒换;
不可重置dbe_perf.statement视图。
3. 报告核心内容(表格)
|
报告类型 |
模块 |
核心指标 |
适用级别 |
|
Summary |
Load Profile |
DB Time/CPU Time、SQL 响应时间(P80/P95)、事务数 / SQL 执行次数 |
集群 |
|
|
Instance Efficiency Percentages |
Buffer 命中率(目标 100%) |
集群 / 节点 |
|
|
Top 10 Events by Total Wait Time |
等待事件总时长 / 平均时长 / 次数 |
节点 |
|
|
Host CPU |
CPU 核数、用户态 / 系统态 / 空闲态占比 |
节点 |
|
|
IO Profile |
表 / 索引 IO 次数(MB)、WAL IO 量 |
集群 / 节点 |
|
Detail |
Time Model |
DB_TIME/EXECUTION_TIME/NET_SEND_TIME/DATA_IO_TIME |
节点 |
|
|
SQL Statistics |
SQL 执行次数 / 总时延 / 物理读 / 排序溢出 |
集群 / 节点 |
|
|
Wait Events |
等待事件类型(IO/LOCK/LWLOCK/STATUS)、总时长 / 失败次数 |
节点 |
|
|
Cache IO Stats |
表 / 索引物理读 / 缓存命中数、命中率 |
集群 / 节点 |
|
|
Object Stats |
表扫描次数 / 行增删改、索引扫描次数 |
集群 / 节点 |
|
|
Configuration settings |
GUC 参数当前值 / 默认值 / 取值范围 |
节点 |
4. 典型应用场景
场景 1:响应时间分析:查看 Summary→Load Profile,若 P95 响应时间 > 1s,定位 Top SQL(Detail→SQL Statistics 按总时延排序);
场景 2:缓存命中率低:Summary→Instance Efficiency Percentages,若 Buffer 命中率 < 95%,调整shared_buffers参数;
场景 3:异常等待:Detail→Wait Events,若STATUS wait cmd总时长过高,排查会话阻塞(关联dbe_perf.session_stat_activity)。
三、SQL 优化
1. SQL 执行机制与执行计划
执行流程:
解析(Parser):词法→语法分析生成语法树,语义分析生成查询树;
优化(Planner):查询重写(简化 SQL)→路径生成→代价计算,选择最优计划;
执行(Executor):按计划树调用算子,访问表 / 索引执行 SQL。
执行计划查看:通过EXPLAIN命令,支持多选项:
EXPLAIN (costs off):不显示代价;
EXPLAIN (analyze on):执行 SQL 并显示实际耗时;
EXPLAIN (nodes on):显示执行节点。
2. 核心算子分类(表格)
|
算子类型 |
代表算子 |
功能 |
适用场景 |
|
扫描算子 |
SeqScan |
顺序扫描行存表 |
无索引或数据量小 |
|
|
IndexScan |
索引扫描,需回表取数 |
过滤条件匹配少量数据 |
|
|
IndexOnlyScan |
仅索引返回结果,无需回表 |
查询列完全覆盖索引 |
|
|
CstoreScan |
扫描列存表 |
OLAP 场景海量数据查询 |
|
关联算子 |
NestLoop |
嵌套循环连接,适合小表关联 |
外表小、内表有索引 |
|
|
HashJoin |
哈希连接,构建哈希表匹配 |
大表关联,内存充足 |
|
|
MergeJoin |
归并连接,需先排序 |
两表已排序或有排序索引 |
|
物化算子 |
Sort |
对数据排序 |
ORDER BY/GROUP BY |
|
|
Agg |
聚合计算(COUNT/SUM) |
含聚合函数的 SQL |
|
|
Hash |
构建哈希表 |
HashJoin/Agg 算子前置 |
|
控制算子 |
Result |
处理单条计算或INSERT VALUES |
简单值计算 |
|
|
ModifyTable |
执行INSERT/UPDATE/DELETE |
数据修改操作 |
3. 关键调优工具与策略
(1)参数调优
|
参数名称 |
功能 |
关键说明 |
|
|
max_process_memory |
控制实例最大内存 |
作业可用内存 = 该值 -shared_buffers-cstore_buffers |
|
|
work_mem |
控制算子下盘阈值 |
超过该值,Hash/Agg/Sort 算子下盘,默认 4MB,大查询需调大 |
|
|
enable_xxxscan |
开启 / 禁用扫描算子 |
如enable_seqscan=off禁用顺序扫描,强制走索引 |
|
|
enable_xxxjoin |
开启 / 禁用连接算子 |
如enable_hashjoin=on优先使用哈希连接 |
|
|
query_dop |
控制 SMP 并行度 |
0 = 自适应(1~8),-value = 限制最大并行度,value = 强制并行度 |
|
(2)Plan Hint(手工干预计划)
|
Hint 类型 |
语法 |
功能 |
|
|
扫描 Hint |
/*+ tablescan(table) */ |
强制对 table 使用顺序扫描 |
|
|
|
/*+ indexscan(table index) */ |
强制对 table 使用指定索引扫描 |
|
|
连接 Hint |
/*+ nestloop(table1 table2) */ |
强制 table1 与 table2 用嵌套循环连接 |
|
|
|
/*+ hashjoin(table1 table2) */ |
强制 table1 与 table2 用哈希连接 |
|
|
连接顺序 Hint |
/*+ leading(t1 (t2 t3)) */ |
强制 t2 与 t3 先连接,再与 t1 连接 |
|
|
行数 Hint |
/*+ rows(t1 t2 #100) */ |
指定 t1 与 t2 连接后结果集行数为 100 |
|
(3)业务适配调优
|
业务类型 |
调优策略 |
关键参数 / 技术 |
|
|
交易类 |
CN 轻量化 |
enable_light_proxy=on(简单查询 CN 直接执行) |
|
|
|
减少分布式事务 |
DML 指定分布列过滤,下推至单 DN 执行 |
|
|
|
计划缓存 |
plan_cache_mode=auto(自动选择通用 / 自定义计划) |
|
|
混合负载类 |
SMP 并行 |
query_dop=0(自适应并行度,资源充足时性能提升 2~4 倍) |
|
|
|
存储倾斜 |
调整分布列(选择离散值列),通过table_skewness(表名)检查倾斜 |
|
|
|
计算倾斜 |
RLBT(Runtime Load Balance),skew_option=on,自动识别倾斜数据并轮询分配 |
|
4. 统计信息与分布式计划
统计信息:优化器依赖的表 / 列数据分布信息,通过ANALYZE更新,存储于pg_statistics/pg_stats,核心指标包括列空值率、唯一值数、最常见值(MCV);
分布式计划:
下发 SQL 语句:各 DN 独立执行,无数据交互(如单表过滤);
下发 SQL 计划:CN 生成计划,DN 执行并交互数据(如多表关联);
下发部分 SQL:CN 执行部分逻辑,DN 执行基表扫描(极少数场景)。
2.4 关键问题
问题 1:如何通过系统级指标定位 GaussDB 集群的 CPU 瓶颈?需结合哪些视图和指标?
答案:定位 CPU 瓶颈需从 “系统级 CPU 使用” 和 “应用级 CPU 消耗” 两方面入手,核心步骤与视图如下:
查看系统级 CPU 负载:
调用视图dbe_perf.os_runtime,关注指标:NUM_CPU_CORES(CPU 核数)、BUSY_TIME(CPU 繁忙时间)、USER_TIME(用户态时间)、SYS_TIME(系统态时间)、IOWAIT_TIME(IO 等待时间);
若BUSY_TIME占比 > 80% 且IOWAIT_TIME占比 < 10%,说明 CPU 饱和(非 IO 导致)。
定位 CPU 消耗来源:
查看dbe_perf.instance_time,对比CPU_TIME(总 CPU 时间)与DB_TIME(作业有效时间),若CPU_TIME接近DB_TIME,说明 CPU 是瓶颈;
查看dbe_perf.session_stat_activity,筛选state='active'的会话,按now()-query_start排序,定位长期占用 CPU 的活跃 SQL;
查看dbe_perf.statements,按cpu_time排序,找出 CPU 消耗 Top SQL(如聚合 / 排序操作)。
验证与优化:
对 Top SQL 执行EXPLAIN ANALYZE,检查是否存在全表扫描、排序下盘(Sort Spill),通过添加索引、调大work_mem减少 CPU 消耗;
若 CPU 核数不足,考虑扩容节点或调整业务并发度。
问题 2:WDR 报告中 “Top 10 Events by Total Wait Time” 显示 “STATUS wait cmd” 等待事件总时长过高,如何分析并解决该问题?
答案:“STATUS wait cmd” 属于 STATUS 类等待事件,通常与 SQL 执行过程中命令等待(如 GTM 交互、连接池获取)相关,分析与解决步骤如下:
细化等待事件信息:
查看 WDR 报告 Detail→Wait Events 模块,获取该事件的Waits(等待次数)、Avg Wait Time(平均等待时间)、Max Wait Time(最大等待时间);
若Avg Wait Time>1000us 且Waits次数多,说明存在频繁的命令等待,需进一步定位等待场景。
关联会话与 SQL:
结合dbe_perf.session_stat_activity(快照时段数据),筛选wait_event='wait cmd'的会话,获取对应的query(执行 SQL);
若 SQL 涉及 GTM 操作(如事务提交、获取快照),检查dbe_perf.wait_events中gtm commit trans/gtm get snapshot事件的等待时长,可能是 GTM 节点负载过高;
若 SQL 涉及连接池操作,查看dbe_perf.global_pooler_status,检查wait pooler get conn事件,可能是连接池容量不足。
针对性解决:
若 GTM 负载高:切换为 GTM-Lite 模式(减少中心节点负载),或扩容 GTM 节点;
若连接池不足:调大pooler_max_connections(连接池最大连接数),或优化应用连接复用(如增加连接池超时时间);
若 SQL 本身耗时久:对 SQL 进行优化(如添加索引、简化逻辑),减少命令执行时长。
问题 3:GaussDB 混合负载场景下出现数据倾斜(某 DN 数据量是其他节点的 2 倍),如何通过 SQL 优化手段解决?
答案:混合负载场景的数据倾斜分为 “存储层倾斜”(分布列不当)和 “计算层倾斜”(重分布导致),需分场景优化:
1. 存储层倾斜(分布列选择不合理)
诊断: 执行select table_skewness('表名');,若某 DN 数据占比 > 平均占比 10%(如 18 个 DN 平均 5.5%,某 DN 占 8%),判定为存储倾斜。
解决:
重新选择分布列:遵循三大原则 ——①选择离散值多的列(如用户 ID,避免性别);②选择关联 / 聚合字段(如订单表按order_id,减少 Join 重分布);③避免常量约束列(如状态列,易集中);
示例:原表按inv_date_sk(日期,离散度低)分布,改为按inv_item_sk(商品 ID,离散度高),执行ALTER TABLE inventory DISTRIBUTE BY HASH(inv_item_sk);,倾斜率从 8% 降至 5.6%。
2. 计算层倾斜(Join/GROUP BY 非分布列)
诊断: 执行EXPLAIN PERFORMANCE,查看各 DN 执行时间,若某 DN 执行时间是其他节点的 3 倍以上(如某 DN 120s,其他 50s),判定为计算倾斜。
解决:
启用 RLBT(Runtime Load Balance Technology):通过ANALYZE更新统计信息,系统自动识别倾斜 Key,非倾斜数据按 HASH 分布,倾斜数据按 RoundRobin 均匀分配;
手工干预:通过 Plan Hint 指定倾斜列,如/*+ skew(inventory (inv_item_sk) (10000) */(指定inventory表inv_item_sk=10000为倾斜值);
调整连接顺序:通过/*+ leading(t1 t2) */强制小表先连接,减少倾斜数据量;若使用 HashJoin,确保小表作为构建表(减少哈希表大小)。
验证: 优化后重新执行table_skewness(存储层)和EXPLAIN PERFORMANCE(计算层),确认各 DN 数据量差异 < 5%、执行时间差异 < 20%,倾斜问题解决。
- 点赞
- 收藏
- 关注作者
评论(0)