给金仓做一次体检:sysbench 压出瓶颈,KWR 报告告诉我“别再加内存了
一、性能优化最贵的不是调参,是调错方向
数据库跑得慢,最常见的处理方式是"凭经验调参"——内存小就加 shared_buffers,慢查询多就加 work_mem。但真实的生产事故里,我见过太多"加了一倍内存、TPS 纹丝不动"的困惑。原因很简单:瓶颈不在你调的那个地方。
Oracle DBA 靠 AWR 报告定位瓶颈,金仓给了对标的武器——KWR(Kingbase Workload Repository,工作负载知识库)。这篇我在鲲鹏服务器上,用 sysbench 给 KingbaseES 压出真实负载,再用 KWR 报告做一次完整体检。故事的结局有点反直觉,但恰恰是它,讲清了性能诊断工具真正的价值。
二、体检对象与工具

-
被测:KingbaseES 企业版,跑在 4 核 7GB 的鲲鹏 ECS 上;
-
加压:sysbench 1.0.20 的
oltp_read_write混合负载(读写比约 7:3),用它的 pgsql 驱动直连金仓 54321 端口,造了一个 10 表 × 10 万行、约 330MB 的sbench库; -
诊断:
sys_kwr扩展(版本 1.8.m1),它就是金仓版的 AWR——按固定间隔给数据库拍"快照",两个快照之间的差异就是一份性能报告。
方法论很简单:拍一张快照 → 压 60 秒 → 再拍一张 → 生成报告。报告告诉我们瓶颈在哪,然后对症下药,调完再压一轮做对比。
三、开工前的三个坑
KWR 不是开箱即用的,我连踩三坑,都值得记下来。

坑一:采集开关出厂默认全关。 sys_kwr.enable、track_sql、track_instance、sys_stat_statements.track 四个开关默认都是 off/none——不打开,快照就是空的,报告自然没数据。而且打开后必须重启实例,采集进程才会真正建起那些内部统计表(我一开始只 reload,快照始终缺表,重启后才好)。
坑二:多条 ALTER SYSTEM 不能塞进一个事务。 我图省事把几条 ALTER SYSTEM SET 用分号连在一个 ksql -c 里执行,直接报 ALTER SYSTEM cannot run inside a transaction block。正解是用 ksql -f 执行脚本文件(每条语句独立提交)。
坑三(最坑):中文/HTML 报告函数有 bug。

我一开始调用 perf.kwr_report_text_cn() 想直接出中文报告,结果报错 relation "kwr_snap_db_sql_time" does not exist。排查后定位到根因:报告函数内部引用了一个叫 kwr_snap_db_sql_time 的表,但采集侧实际建的表叫 kwr_snap_sql_time(少了 db_)。 深挖发现,通用入口 perf.kwr_report() 内部会先调 kwr_create_wrapped_views() 自动创建这批"包装视图"补齐名字差异,而中文版 kwr_report_text_cn、文本版 kwr_report_text、HTML 版 kwr_report_html 都漏掉了这个前置步骤,于是直接撞表不存在。
解法:用通用入口 perf.kwr_report(start_id, end_id, 'text', database),它自洽可用,一次生成了 1368 行完整报告、零报错。
四、基线体检:一张报告看清全身
打开采集、压测 60 秒、生成基线报告。这就是金仓 KWR 报告的真实模样:

信息量很大,抓最关键的三块看:
负载分析——1.02 分钟的墙上时间里,DB Time 高达 11.06 分钟(约 10.8 个活跃会话,对应 16 个压测线程),每秒 1515 个事务、29813 次执行。机器在真忙。
实例效率——Buffer Hit % = 99.58%。这个数字很关键:缓冲命中率已经接近满分,意味着几乎所有数据块都能在内存里找到,物理磁盘读极少。换句话说,内存根本不是瓶颈。
Top 前台等待事件——这是全篇的题眼,它直接告诉你数据库的时间花在了哪:
|
等待事件 |
占 DB Time |
类型 |
|
DB CPU |
82.93% |
CPU 算力 |
|
WALWriteLock |
9.88% |
WAL 写锁 |
|
WALSync |
5.88% |
WAL 刷盘 IO |
|
DataFileRead |
0.40% |
数据文件读 |
真相大白:82.93% 的时间在烧 CPU,其次是 WAL 写(锁+刷盘合计约 15.7%),而数据文件读只占 0.4%。这是一个典型的 CPU 密集型负载,4 个核心被 16 个线程榨得干干净净。
如果没有这张报告,我大概率会去加 shared_buffers——毕竟出厂只有 128MB,直觉上"太小了"。但报告清清楚楚地说:内存命中率 99.58%,加内存是无用功,你的瓶颈是 CPU。
五、对症下药
虽然报告已经暗示"CPU 才是墙",但我还是想验证一件事:那约 16% 的 WAL 等待,调优能不能压下去?同时把 shared_buffers 这些内存参数一并调到位,看它们到底有没有用。出厂参数确实保守:

调优思路是跟着报告走,不是拍脑袋:
-
报告说 WAL 是第二瓶颈 →
wal_buffers4MB→64MB(缓解 WALWriteLock)、max_wal_size1GB→8GB(拉长 checkpoint 间隔)、commit_delay0→20(组提交合并 WALSync 的刷盘次数); -
顺带验证内存 →
shared_buffers128MB→1.5GB、work_mem4MB→16MB; -
全程保持
synchronous_commit = on,不靠牺牲数据持久性来刷分,保证对比公平。
改完重启,参数生效,同样的 60 秒压测再来一轮。
六、结局反转,也是全篇最有价值的一课

|
指标 |
基线 |
调优后 |
解读 |
|
TPS(每秒事务) |
1515 |
1528 |
几乎持平(差异在噪声内) |
|
物理读(MB) |
1339 |
205 |
暴降 85% |
|
Buffer Hit % |
99.58 |
99.93 |
命中率再上一层 |
|
DB CPU 占比 |
82.93% |
82.64% |
始终 >82%,真瓶颈 |
这个结果需要认真解读,因为它同时包含"调优有效"和"调优无效"两个看似矛盾的事实:
调优确实起作用了——在它该起作用的地方。 shared_buffers 从 128MB 加到 1.5GB 后,物理读从 1339MB 暴降到 205MB(-85%),缓冲命中率升到 99.93%,WAL 缓冲等待也消失了。这些都是实打实的改善,证明参数调对了地方、生效了。
但 TPS 纹丝不动(1515→1528,属于测量波动)。 为什么?因为 DB CPU 始终占据 82% 以上——这是一个 CPU 密集型负载,4 核的算力就是天花板。物理读降了 85% 又如何?IO 本来就只占 0.4%,它从来不在关键路径上。你把一条空闲车道拓宽了 10 倍,堵车的主干道还是那条 CPU。
这就是 KWR 报告最大的价值——它不是用来"一调就快"的魔法,而是帮你避免做无用功。 它在第一份报告里就明明白白地告诉我:"命中率 99.58%,你的瓶颈是 CPU 不是内存。"如果我无视它、一头扎进内存调优,我会得到一个哭笑不得的结果:物理读降了 85%,性能却没涨,然后百思不得其解。
真正能提升这个负载的方向,报告也指明了:要么加 CPU 核数(4 核换 8 核、16 核),要么优化 SQL 逻辑降低单次执行的 CPU 消耗(报告里 Plan Reused 只有 80%,计划缓存还有文章可做)。调内存,此路不通。
七、结论
我用 sysbench 给金仓压出真实负载,用 KWR 报告完成了一次完整体检。故事的结局不是俗套的"一调 TPS 涨三成",而是更真实的一课:
基线 1515 TPS,调优后 1528 TPS,几乎没变。但这不是失败——恰恰是 KWR 报告的成功。 它在压测的第一分钟就看穿了本质:这是 CPU 密集型负载,缓冲命中率 99.58% 已经说明内存不是问题。是它让我没有把时间浪费在"加内存求快"的死路上,而是清楚地知道——下一步该加的是 CPU,不是内存。
性能优化领域有句老话:没有度量,就没有优化。 金仓的 KWR,就是国产数据库给 DBA 的那把尺子。它未必让你的库瞬间变快,但它能让你的每一次调优都调在刀刃上——这比什么都值钱。
鲲鹏昇腾开发者社区是面向全社会开放的“联接全球计算开发者,聚合华为+生态”的社区,内容涵盖鲲鹏、昇腾资源,帮助开发者快速获取所需的知识、经验、软件、工具、算力,支撑开发者易学、好用、成功,成为核心开发者。
更多推荐

所有评论(0)