
测试环境为鲲鹏 aarch64、银河麒麟高级服务器 V10Tercel、KingbaseES V009R001C010 企业版180 天授权。文中所有压测与 SQL 实验数据均为本机真实采集附录给了完整的复现命令。先把结论放在前面。同一台机器、同一份数据、同样的压测命令只改了十来个内存和 WAL 参数4 并发只读压测的 TPS 中位数从 54,029 涨到 70,541各采样 5 次取中位数提升约 30.6%。SQL 层面更夸张一点一条主键精确查询加索引之前 94ms加完 0.034ms差了大约 2700 倍。但同一张表上另一条命中 20% 行的范围查询索引建了等于白建优化器看都不看一眼照样全表扫描。这几个数字放在一起差不多就是这篇文章想讲的事。调优不是玄学也不是无脑加索引、无脑堆硬件它更像是先搞清楚数据库到底在忙什么再把资源花在刀刃上。做这次实验的起因很简单。手上正好有一台鲲鹏测试机装的是银河麒麟 V10又申请到了金仓 KES V9 的企业版授权一套很典型的信创组合。平时总能听到一种说法「国产数据库性能不行」。但我一直怀疑这口锅有相当一部分要默认参数来背。数据库出厂配置是面向通用场景的128MB 的 shared_buffers 放在今天任何一台服务器上都显得寒酸更不会针对鲲鹏这种 ARM 平台做什么适配。默认参数直接上线跑不快然后得出结论说产品不行这个链条其实换成哪家数据库都逃不掉。所以我想亲手验证一件事同样的负载经过一轮有章法的调优这套全栈国产组合到底能压出什么样的表现。重点不在最后那个数字在方法先用 KWR 报告把瓶颈找准再动手而不是拍脑袋调参。整体思路。基线压测、KWR 诊断、参数与 SQL 调优、复测对比一个闭环文中每个数字都有对应的截图或报告佐证。一、测试环境配置相当入门4 核鲲鹏7 个多 G 内存。如果你手头的信创环境也是这种规格后面的参数基本可以直接抄。项配置CPUHiSilicon ARMv8aarch644 核 2.9GHz单 NUMA 节点内存7314 MB无 swap磁盘39G SSDvda系统盘操作系统银河麒麟高级服务器 V10Tercel内核 4.19.90-17.5.ky10.aarch64数据库KingbaseES V009R001C010企业版 180 天授权安装与数据目录/opt/Kingbase/ES/V9 和 /data端口 54321压测工具kbbench金仓自带scale50约 500 万行lscpu、free、系统版本与数据库版本的真实输出确认 aarch64、麒麟 V10、KES V9 这套组合。二、先钉死基线调优最忌讳的一件事改了一堆参数然后凭感觉说「快了」。所以动手之前先在完全默认的出厂参数下shared_buffers128MB、work_mem4MB 这种状态压一轮把起点钉死。工具用金仓自带的 kbbench。数据规模 scale50约 500 万行4 并发 4 线程select-only 负载跑 60 秒模拟最常见的只读业务。跑出来5 次采样 55,481、49,076、49,648、54,029、62,723取中位数 TPS 54,029。这就是基线。后面所有对比都用同一份数据、同一条压测命令唯一的变量是数据库参数。默认参数下 kbbench 4 并发 60 秒连续执行 5 次采样值 55,481、49,076、49,648、54,029、62,723中位数 TPS 54,029。三、KWR 报告先搞清楚数据库在忙什么按不少人的习惯拿到基线就该开始调参了。我停了一下先回答一个问题瓶颈到底在哪。金仓给的工具是 KWR全称 Kes Workload Repository用过 Oracle AWR 的朋友会觉得非常眼熟思路一模一样打两个快照生成一份报告把这段时间数据库的负载、等待事件、Top SQL 全部摊开给你看。开启也不复杂。建一个 sys_kwr 扩展把 track_sql、track_instance 这些统计参数打开压测前后各打一次快照再用 perf.kwr_report_to_file 把报告导出来。通过 perf.kwr_report_to_file 生成报告快照列表完整覆盖了压测周期。报告摊开信息量很大但真正关键的就几行。DB Time 一共 328.17 秒其中 DB CPU 占了 328.15 秒99.99%。数据库的时间几乎全部花在计算上这是一个纯得不能再纯的 CPU 密集负载。再看缓存Buffer Hit 100.00%Buffer NoWait 也是 100.00%500 万行数据基本全躺在共享缓冲区里磁盘每秒的写操作只有 4.47 次约等于没有。等待事件那一栏更直接Top 等待清一色是 DB CPUIO 类等待加起来总共 0.03 秒占 0.01%磁盘彻底洗清了嫌疑。报告里的负载概览DB Time 328.17 秒DB CPU 328.15 秒占 99.99%Buffer Hit 100.00%、Buffer NoWait 100.00%磁盘每秒写仅 4.47 次。Top 等待事件几乎全是 DB CPUIO 类等待只占 0.01%。还有一个数字我盯了很久。Parse Calls 每秒 51,060 次而 Parse Reused 是 0.00%。每条 SQL 每次执行都在从头解析一次复用都没有。这次没来得及处理它但它明摆着是下一步的优化空间文末再提。Top SQL 也很干净kbbench 的主查询 SELECT abalance 一条占掉 91.95% 的数据库时间执行了 617 万次。Top SQL 统计SELECT abalance 占数据库时间 91.95%执行 617 万次。到这里诊断结论其实已经写好了。这个场景下加内存没用数据本来就全在内存里。换更快的盘更没用IO 压根不是瓶颈。真正值得投入的只有一件事让 CPU 少干活。这份十分钟出来的报告省掉的是盲目堆硬件的冤枉钱也直接定下了后面调优的方向减少解析开销优化执行路径把内存用对地方。四、参数怎么调方向定了接下来针对 4 核、7.3G 内存这个小配置做适配。改动全在下面这张表里每条都写了我的理由。参数默认值调优值为什么这么调shared_buffers128MB1536MB约 20% 物理内存扩大数据缓冲同时给系统页面缓存留空间effective_cache_size4GB4608MB约 60% 内存让优化器对可用缓存有正确预期work_mem4MB16MB匹配 4 并发下的排序和哈希需求maintenance_work_mem64MB256MB给 VACUUM 和建索引提速max_connections100200预留并发连接余量checkpoint_completion_target0.50.9把刷盘摊平压低 IO 峰值wal_buffers4MB16MB提升 WAL 写入吞吐max_wal_size1GB2GB降低 checkpoint 频率synchronous_commitonoff测试场景看吞吐上限生产环境按业务要求权衡track_sql / track_instance / track_io_timing 等offon给 KWR 深度诊断喂数据这里面有两个点想单独说说。一个是 shared_buffers 不是越大越好。总共就 7.3G 内存我取了 1536MB大约 20%给操作系统的页面缓存留足空间。数据库缓存和文件系统缓存抢内存是小内存机器上很经典的翻车姿势。另一个是 effective_cache_size 必须跟着一起调它本身不占内存只是告诉优化器系统里大概有多少缓存可用。这个值要是留着默认不动优化器会低估可用缓存然后在执行计划的选择上变得保守甚至出错。还有 synchronous_commitoff 这条要说清楚这是测试场景为了看写入吞吐上限才关的。生产环境关不关得按业务对数据丢失的容忍度来权衡这一条不能照抄。参数以追加方式写进 kingbase.conf重启数据库用 sys_settings 确认全部生效。调优参数追加写入 kingbase.conf每条都注明了适配 4 核 7.3G 配置的理由随后重启生效。重启后 sys_settings 的输出shared_buffers 显示 196608 个 8kB 页正好 1536MB其余参数同样已生效。五、SQL 层的两个对照实验参数解决的是数据库层面的问题SQL 优化解决的是语句层面的问题。很多人对 SQL 优化的全部理解就是一句话「慢就加索引」。我在一张 200 万行的表上做了两组对照实验结果正好一正一反。先建表id、val、created 三个字段插 200 万行created 按秒递增具体语句见附录。第一组对 created 做范围查询查 1 月 1 号到 15 号之间的数据命中大约 40 万行占全表 20%。没索引的时候走 Parallel Seq Scan222ms。然后我把索引建上再跑一遍。优化器看了一眼索引没理还是 Parallel Seq Scan179ms。created 范围查询的 EXPLAIN ANALYZE 对比命中约 20% 的行无索引 222ms建了索引优化器仍选 Seq Scan179ms。第一次碰到这种情况的人多半会懵索引白建了其实优化器是对的。命中 20% 的行还硬走索引等于要做几十万次随机 IO 回表成本比顺着把表扫一遍高得多它不用你的索引恰恰说明它算得清这笔账。这种查询真正的优化方向不是索引是从源头减少扫描量做分区裁剪或者把过滤条件收得更紧。第二组对 id 做精确匹配id 1234567,200 万行里就找这一行。没索引Parallel Seq Scan94ms。建上索引Index Scan0.034ms。差了大约 2700 倍。id 精确匹配的对比无索引全表扫描 94ms有索引走 Index Scan仅 0.034ms。同样是加索引一边几乎无感一边是数量级的碾压分水岭就在选择性上。返回行数占比越低索引越值钱占比一高索引就成了摆设。所以我现在的习惯是碰到慢 SQL第一件事永远是 EXPLAIN ANALYZE看三样东西一看走的是什么访问路径Seq Scan 还是 Index Scan二看命中行数占全表多大比例三看有没有多余的排序、重复扫描、隐式类型转换。优化器不傻它只能基于你喂给它的东西做决策统计信息、索引、参数这些就是它的全部依据。调优的人真正的价值是把信息喂对。六、复测对比参数全部生效之后用和基线一模一样的条件复测同一份数据4 并发60 秒。TPS 中位数从 54,029 涨到 70,541提升 30.6%均值提升 22.0%。为了排除偶然两组配置均多次采样后结论稳定趋势一致。调优后同条件复测连续执行 5 次采样值 70,541、70,614、59,106、62,362、70,558中位数 TPS 70,541。指标调优前默认参数调优后变化TPS 中位数5次采样54,02970,54130.6%采样波动范围27.8%19.5%—Buffer Hit/100%无 IO 瓶颈DB CPU 占比/99.99%纯 CPU 场景高选择性 SQL加索引前后94 ms0.034 ms约 2700 倍调优前后 TPS 对比数据来自本机 kbbench 实测2026-08-05同一配置采样 5 次取中位数统一关闭统计采集基线为默认参数调优参数见第四节。30.6% 这个数字按中位数单看不算惊艳我也不打算把它吹成什么奇迹。但要注意前提默认配置在这个场景下已经把缓冲命中率打到了 100%内存层面基本没有油水可榨这 30.6% 是从 CPU 解析和执行路径的开销里挤出来的在这种负载下已经算相当实在的收益了。而且这是纯只读场景如果业务里有大量写入checkpoint 平滑、WAL 缓冲加大和 synchronous_commit 这些调整的效果会比现在明显得多。调优这件事与其指望某个一改就起飞的魔法参数不如老老实实把每一分硬件资源都用到位。七、写在最后这轮实验做完我自己留下三条心得。先诊断再动手。KWR 报告十分钟就确认了「CPU 密集、IO 无瓶颈」这个关键事实后面所有动作都是照着这个结论做的一步冤枉路没走。反过来不看报告直接调参多半是在碰运气。参数要贴着硬件和负载调。同一套参数换个机器规格未必还对这也是我反复强调 4 核 7.3G 这个前提的原因。SQL 优化的钥匙是选择性不是索引本身。低选择性的查询索引建了也白建高选择性的查询一个索引换来 2700 倍。看懂 EXPLAIN ANALYZE比背十条优化口诀有用。跑完这一轮我更确信很多时候差的不是产品是那套还停在出厂状态的默认参数。KWR 报告、EXPLAIN ANALYZE、一整套可调参数工具都摆在那了能不能压出性能看的是会不会用。全部实验都可以照着下面的清单复现有兴趣的朋友可以在自己的环境里跑一遍。附录 可复现命令清单# 1. 环境确认lscpu|grep-EArchitecture|CPU\(s\):|Model namefree-m;cat/etc/kylin-release# 2. 启动数据库(如未启动)exportLD_LIBRARY_PATH/opt/Kingbase/ES/V9/Server/lib /opt/Kingbase/ES/V9/Server/bin/sys_ctl-D/data-l/data/server.log start# 3. 安装 KWR 扩展/opt/Kingbase/ES/V9/Server/bin/ksql-Usystem-dbench-p54321-ccreate extension sys_kwr;# 4. 初始化压测数据(scale50, 约500万行)/opt/Kingbase/ES/V9/Server/bin/kbbench-Usystem-p54321-i-s50bench# 5. 基线压测(默认参数)/opt/Kingbase/ES/V9/Server/bin/kbbench-Usystem-p54321-c4-j4-T60-Sbench# 6. 手工打 KWR 快照ksql-Usystem-dbench-p54321-cselect * from perf.create_snapshot();# 7. 生成 KWR 报告(指定快照区间)ksql-Usystem-dbench-p54321-cselect perf.kwr_report_to_file(1, 2, text, /home/kingbase/kwr_out/kwr.txt);# 8. SQL 优化对比实验(200万行)ksql-Usystem-dbench-p54321-ccreate table t_slow (id bigint, val varchar(64), created timestamp);ksql-Usystem-dbench-p54321-cinsert into t_slow select g, data_||g, timestamp 2026-01-01 (g*interval 1 second) from generate_series(1,2000000) g;# 8.1 低选择性范围查询, 无索引时观察 Seq Scanksql-Usystem-dbench-p54321-cexplain analyze select count(*) from t_slow where created timestamp 2026-01-01 and created timestamp 2026-01-15;# 建索引后再跑一遍, 观察优化器是否仍选 Seq Scanksql-Usystem-dbench-p54321-ccreate index idx_t_slow_created on t_slow(created);ksql-Usystem-dbench-p54321-cexplain analyze select count(*) from t_slow where created timestamp 2026-01-01 and created timestamp 2026-01-15;# 8.2 高选择性精确查询, 无索引与有索引对比ksql-Usystem-dbench-p54321-cexplain analyze select * from t_slow where id 1234567;ksql-Usystem-dbench-p54321-ccreate index idx_t_slow_id on t_slow(id);ksql-Usystem-dbench-p54321-cexplain analyze select * from t_slow where id 1234567;# 9. 调优后复测, 命令与第 5 步完全一致/opt/Kingbase/ES/V9/Server/bin/kbbench-Usystem-p54321-c4-j4-T60-Sbench