SQL Server数据迁移到金仓数据库复盘:从怕性能翻车,到TPS提升60%

一、先说背景,一台SQL Server撑了八年

我在一家连锁零售企业干活,职位写的是DBA,实际数据库的活我干,后端的锅我也背,公司人少,没那么多讲究。手里这套ERP跑了八年,订单、库存、会员三个大模块,外加十来张BI报表,底座是SQL Server 2016标准版,数据1.4TB,表423张,存储过程136个。

去年11月,两件事撞一块了。一件是SQL Server按核数授权的续约费用又涨了,采购把报价单转给我的时候附了三个字:"你看看"。另一件是公司层面下了国产化替代的通知,年底前完成,白纸黑字。

领导把我叫进会议室,原话大概是:"选型你来定,出了事你负责。"我点头点得挺痛快,走出会议室腿有点软。

不是怕迁移本身,是怕性能翻车。BI报表月底高峰本来就慢,业务群里天天有人@我,截图配文"这报表是在转圈还是睡着了"。这要是换完库更慢,我真没法做人。

@TOC

二、迁移前夜,我打鼓的三个地方

选型最后定了金仓数据库,KES V9R4C019,SQL Server兼容模式。中间POC测了两轮,过程不啰嗦,就说拍板前我自己心里过不去的坎。

最愁的是那136个存储过程。MERGE、OUTPUT、TOP配ORDER BY,什么写法都有,还有一坨是离职同事留下的,注释一个字没有。真要人肉改语法,这活儿看不到头。

再一个就是性能,尤其是标量子查询。我们一堆报表SQL在SELECT列表里挂子查询,在SQL Server上靠索引硬扛着,属于数据量再涨涨就要出事的写法。换个引擎还扛不扛得住,没人敢打包票。

还有件事我没好意思跟领导说:半夜库挂了咋办。SQL Server我们熟,闭着眼都能处理;换了新库,排障、备份、恢复全得从头学。这个怕,说出来显得自己没本事,只能自己消化。

三、方案怎么定的

方案不复杂,电科金仓的工具链分工挺清楚。KDMS管前期评估,连上源库采集对象,出评估报告,能自动转的语法直接转,转不了的给改写建议。数据搬迁用KDT和KFS,全量加增量同步,最后在停机窗口里追平、校验。切换前还有一道真实流量回放,把生产流量录下来在目标库跑一遍,坑提前踩。

KDMS报告出来那天,我盯着看了半个多小时。136个存储过程,128个标了可自动转换,剩8个要人工------全是动态SQL拼EXEC的,工具确实啃不动,手工搬。1.4TB全量过下来,比预想的顺。

后来给领导汇报,工作量汇成这么一张表:

对象类型 总数 自动转换 人工处理 备注
423 423 0 含6张分区表
存储过程/函数 160 152 8 动态SQL手工搬
视图 58 57 1 有个TOP 100 PERCENT的写法
索引 310 296 14 顺手清了批无效索引
自增列 46 46 要手工重置序列 埋了坑,后面细说

表打出来我自己先看了一遍,别的行都挺体面,就最后一行那个备注,写的时候心里就咯噔了一下。你们猜怎么着,还真就它炸了。

四、踩坑实录

自增列断号,功能测试第一天就给我下马威

全量数据迁完,功能测试第一天下午,下单接口报主键冲突,duplicate key。

我第一反应是迁移工具丢数据或者搬重了,拉着同事核行数核了快半小时,一条不差。那冲突哪来的?

接着看报错那条数据。插入的订单ID是10583万,表里最大ID是10582万,下一个号就该是10583万,没毛病啊?再往下抠才发现,问题不在表里,在序列上。兼容模式下自增列是走序列发号的,序列的当前值还停在初始位置,压根不知道表里已经发到一亿多了。数据是数据,序列是序列,工具把数据搬过来了,序列不会自己跟着涨。

修起来不难,拿表内最大值把序列顶上去就行:

sql 复制代码
-- 先看序列当前值,果然还在1附近
SELECT last_value FROM t_orders_order_id_seq;

-- 用表内最大值重置序列,false表示下一个号从max+1开始发
SELECT setval('t_orders_order_id_seq',
              (SELECT COALESCE(MAX(order_id), 1) + 1 FROM t_orders),
              false);

46张带自增列的表,我写了个脚本遍历跑完,前后十来分钟。但这事教训挺深:校验别光核行数和checksum,序列、默认值这类元数据也得进核对清单。后来我把它写进我们组的迁移检查单了,排第七条。

统计信息这坑,差点让全组心态崩了

第二个坑藏得深,杀伤力也大。

切换前做100并发压测,第一轮TPS跑出来141。基准多少?SQL Server上是235。六成。会议室里安静了几秒,后排有人小声来了句"果然不行"。说实话我血压也上来了,但骂库没用,拉执行计划吧。

EXPLAIN一出来就看到问题了,一条核心关联查询的索引走错了,明明有现成的组合索引,优化器偏偏选了另一个。看了半天没想通,下午四点多打电话给原厂支持,对方听完就问了一句:统计信息收集过吗?

......对啊,收集过吗?没有。

新库刚建好,统计信息要么是空的要么抽样极粗,优化器跟蒙着眼选路没区别。赶紧补:

sql 复制代码
-- 全库收集统计信息
ANALYZE;

-- 重点大表单独再来一遍,让优化器看清数据分布
ANALYZE t_orders;
ANALYZE t_deal_price;
ANALYZE t_member;

再压,TPS从141直接拉到302。一行代码没改,就是让优化器把数据看清楚了。这课我记到现在:换了库先ANALYZE,再谈性能,顺序不能反。

标量子查询,真正的刺客藏在SELECT列表里

统计信息补完,整体达标了,但离官方说的"100并发复杂查询TPS提升60%"还差一截。我们卡在330上下,对235的基准,提升也就四成。

卡在哪?就是前面说的那条含标量子查询的多表关联查询。报表SQL大概长这样,简化过的:

sql 复制代码
SELECT o.order_id,
       o.customer_id,
       o.amount,
       -- 每行都去查一次"该会员最近成交价",行数一大就是灾难
       (SELECT TOP 1 p.deal_price
          FROM t_deal_price p
         WHERE p.customer_id = o.customer_id
         ORDER BY p.deal_time DESC) AS last_price
  FROM t_orders o
 WHERE o.order_date >= '2026-06-01'
   AND o.status = 2;

这种写法数据量小的时候真没毛病,涨起来之后等于每行订单都单独跑一次子查询。SQL Server当年也慢,靠索引硬扛;换了引擎,同样的坑换了个姿势疼。

这次帮上大忙的是金仓内置的QueryMapping。它能做模糊匹配,把长得像的SQL归到一起比执行差异。不查不知道,"查会员最近成交价"这一个逻辑,各分支团队写出了十几个变体,散在七八张报表里,各有各的慢法。工具直接给了改写建议,统一改成LEFT JOIN派生表加窗口函数:

sql 复制代码
SELECT o.order_id, o.customer_id, o.amount, t.last_price
  FROM t_orders o
  LEFT JOIN (
       SELECT customer_id, deal_price,
              ROW_NUMBER() OVER (PARTITION BY customer_id
                                     ORDER BY deal_time DESC) AS rn
         FROM t_deal_price
  ) t ON t.customer_id = o.customer_id AND t.rn = 1
 WHERE o.order_date >= '2026-06-01'
   AND o.status = 2;

再补两个索引:

sql 复制代码
CREATE INDEX idx_dealprice_cust_time ON t_deal_price (customer_id, deal_time DESC);
CREATE INDEX idx_orders_cust_date    ON t_orders (customer_id, order_date);

这一批改完,TPS稳在376,对SQL Server基准正好提升60%;平均响应从4.2秒压到0.42秒,十分之一。跟官方发布的实测数据基本咬上了,我心里那块石头才算落地。

五、性能数据

切换后跑完一个完整月底高峰,跟切换前的压测放一起:

场景 SQL Server 2016 金仓V9R4C019 变化
100并发复杂查询TPS(含标量子查询) 235 376 +60%
同场景平均响应时间 4.2s 0.42s 约1/10
同场景P95响应时间 9.8s 1.1s 降了约89%
月度销售汇总报表(单条大SQL) 8分36秒 4.2秒 122倍左右
月底结账整体窗口 5.5小时 2.1小时 缩短62%

这表看着提气,但我得说两句实话,不然你们真以为换库跟点外卖一样简单。

首先,"报表秒出"不是迁完自动就有的。刚迁完没调优那阵子,那张月度汇总报表要跑3分多钟,比SQL Server还慢。是补统计信息、清无效索引、改标量子查询三板斧全下去,才降到4秒出头。性能是调出来的,不是迁出来的,这话我现在跟谁都说。

另外业务那边的感受最直接。以前月底出报表,同事点完就去泡咖啡,回来还在转;上个月有个小姑娘点完报表愣了一下,跑来问我是不是缓存了旧数据。月底结账窗口从5个半小时压到2小时出头,财务经理专门跑IT这边道了个谢。干DBA八年,头一回。

六、兼容性这事,版本差很多

复盘的时候我反复跟同事念叨,这次顺,有一半要记在版本上。V9R4C019是SQL Server兼容版的一个大节点,好几个能力刚好在这版补齐。

我们日结对账的存储过程重度依赖MERGE,出库单模块用OUTPUT捕获变更写审计日志,这两块在老版本里得人工改写,C019原生支持,存量T-SQL连上去就跑,一行没动。

还有个差点闹笑话的。搜索功能里有句LIKE '[0-9]%',字符集通配符,评估阶段在旧版本上跑报错,当时差点被我当成"兼容性硬伤"写进报告。结果C019直接支持了。所以POC一定拿目标版本测,别拿旧版本下结论,冤枉了产品也耽误自己。

窗口函数、PIVOT/UNPIVOT这些也是这版全面支持的,报表组的同事基本没来找过我的麻烦,这在以前不敢想。

运维侧也有惊喜。内置的故障收集分析工具能自动抓日志、出诊断报告,上线后出过一次连接数异常,从定位到处置5分钟。块级增量备份加PITR最优路径恢复,备份窗口从小时级压到分钟级。这种窗口,原来在SQL Server上我们想都不敢想。

七、最后聊几句

整个项目从KDMS评估到正式切换,现场三周。正式切换是周六晚上,KFS增量追平加数据校验,总停机25分钟。到现在跑过三个月底高峰,稳的。

要说过来的经验,有这么几条,说给后面要做SQL Server数据迁移的同行。

评估一定用对版本。兼容性结论跟版本强相关,C019这种节点版本,可能直接把你改造清单砍掉一大半。

校验清单里加上序列和默认值。行数对上了不代表能写入,自增列断号这种坑,要到第一次插入才爆。

换库后先ANALYZE,再谈性能。统计信息这种看不见的东西,最容易背锅。

标量子查询趁早改。它在哪家库上都是慢性病,趁迁移这个机会拿QueryMapping这类工具全扫一遍,一次把债还了。

给性能对比留够调优时间。裸迁即巅峰这种事不存在,先调完再下结论,对自己对产品都公平。

反正现在谁再问我SQL Server数据迁移能不能搞,我都说能搞。但把坑当成项目的一部分去排,别当成意外。亲眼看TPS从235干到376、响应压到十分之一之后,这话我说得有底气。

相关推荐
HAYDENR1 小时前
数据库如何做性能优化?数据库性能调优有哪些常见注意事项?
数据库·性能优化
Light Gao2 小时前
企业级灰度发布技术方案
网络·数据库·oracle
一水2 小时前
AI 时代审查思维:审查第一篇
java·jvm·数据库·spring
赵广陆2 小时前
企业实战:Milvues向量数据库实践
数据库·pycharm·langchain
微学AI2 小时前
把时间序列真正用起来:TimechoAI 使用与时序分析实战
数据库·人工智能·大模型
cspttty2 小时前
管理类专业证书含金量排名
数据库
怪奇云呼军2 小时前
闪电智能VoiceAgent 如何管理呼入、接听、桥接和挂断状态?
java·前端·网络·数据库·人工智能
秋田君3 小时前
QT_实战TCP 聊天程序说明文档以及实现
数据库·qt·tcp/ip
01_ice3 小时前
MySQL基本查询1
数据库·mysql