当前位置: 代码网 > it编程>数据库>MsSqlserver > SQL Server迁移KingbaseES:复杂BI查询的性能测试和验收

SQL Server迁移KingbaseES:复杂BI查询的性能测试和验收

2026年08月23日 MsSqlserver 我要评论
sql server 数据迁移进入验收阶段后,业务侧问得最多的并不是表迁完了没有,而是报表还能不能像原来一样用。简单查询跑通只能证明连接、对象和基础语法没有问题,真正压在项目组心里的,是那些已经运行多

sql server 数据迁移进入验收阶段后,业务侧问得最多的并不是表迁完了没有,而是报表还能不能像原来一样用。简单查询跑通只能证明连接、对象和基础语法没有问题,真正压在项目组心里的,是那些已经运行多年的 bi 查询:表多、统计口径复杂,sql 中还夹着标量子查询,一到月初或者经营分析会就会同时涌入大量请求。

这次迁移的目标环境是 kingbasees v9r4c019。对象迁移和数据核对完成后,性能验收没有选一条刻意简化的 sql,而是保留了报表系统里较典型的一类查询:订单、明细、客户、区域、商品分类多表关联,再按订单明细计算退款金额。单次执行要处理明细聚合,标量子查询还会引用外层订单明细号,正好能检验迁移后复杂查询的执行效率和并发稳定性。

压测记录给出的结果很直接:100 并发下,复杂查询 tps 比迁移前提升 60%,平均响应时间约为原来的 1/10。原来需要等待较长时间的 bi 报表,在迁移后的环境中能够更快返回。这个结果不是用一条 select 1 得出来的,而是从业务 sql、结果一致性、索引和统计信息一路核对后的迁移验收结果。

迁完对象,只完成了前半程

sql server 到 kingbasees 的迁移,通常先处理表、视图、函数、存储过程、数据类型和数据本身。kingbasees sql server 迁移指南列出了迁移环境、对象和验证路径,这些工作解决的是“能不能迁、能不能运行”。

bi 系统还需要再过一道性能验收。它读取的往往不是单表,而是一组事实表和维度表;一个报表页面可能同时发出多条统计 sql,正常办公时又会出现明显的并发峰值。迁移后的数据库即使每条 sql 都能返回正确结果,只要高并发下排队时间拉长,业务侧仍会觉得迁移没有完成。

因此,验收路径被拆成三个部分:先确认 sql server 原有查询的业务口径,再核对迁移后的对象、类型和结果集,最后观察 kingbasees 上的执行计划、索引命中和并发表现。

这套安排有一个很实际的好处:语法兼容、数据一致性和性能问题不会混在一起。查询报错时先处理兼容;结果不同先查数据和口径;只有结果一致后,tps 和响应时间对比才有意义。

先把迁移口径固定下来

迁移前后的查询不能只比较一条返回记录。报表使用的是一个完整时间窗口,订单状态、退款状态、金额精度和区域分类都要保持相同,时间边界尤其容易被忽略。sql server 中 datetime2 可以保留更细的时间精度,迁移到目标端后,参数类型和比较方式要统一,否则同一秒边界上的订单可能落在不同结果集中。

金额字段也不能在比对时直接转成浮点数。验收表保留 numeric(18,2) 的金额精度,订单数用整数,区域和分类使用迁移后的标准化编码。每个维度先按键排序,再做差集,金额则使用固定的小数位比较。这样查出的差异能对应到具体订单或明细,不会被格式差异掩盖。

select count(*) as row_count,
       sum(gross_amount) as gross_amount,
       sum(refund_amount) as refund_amount,
       sum(net_amount) as net_amount
from verify_report_kingbase
where report_date = date '2026-07-01';

如果总行数相同但金额不同,还要继续按 region_namecategory_name 拆分。迁移工具完成的是数据搬运和对象转换,业务口径仍然要由报表 sql 自己证明。

退款为空和退款为零也要分开确认:没有退款记录时,结果应由 coalesce 转成零;有退款记录但金额为零时,仍然应该保留明细。区域编码、分类编码的大小写和尾部空格也会影响分组结果,迁移后的字符类型、排序规则和清洗逻辑需要与报表原有口径保持一致。只有这些细节都对齐,后面看到的性能变化才是在比较同一件事情。

把原来的复杂查询完整保留下来

报表按区域和商品分类统计已支付订单,同时扣除成功退款。核心数据分布在六张表中:bi_sales_order 保存订单主数据,bi_sales_order_item 保存商品明细,dim_productdim_customerdim_region 提供商品、客户及区域维度,bi_refund 按订单明细记录退款。

sql server 中的原始查询使用 dateaddisnull 和相关标量子查询。退款金额需要按当前订单明细号再次访问退款表,因此它比普通的多表关联更容易放大执行计划选择带来的差异。

declare @begin_time datetime2 = '2026-07-01 00:00:00';
declare @end_time   datetime2 = dateadd(day, 1, @begin_time);

select q.region_name,
       q.category_name,
       count(distinct q.order_id)  as order_count,
       sum(q.gross_amount)         as gross_amount,
       sum(q.refund_amount)        as refund_amount,
       sum(q.gross_amount)
         - sum(q.refund_amount)    as net_amount
from (
    select o.order_id,
           oi.order_item_id,
           r.region_name,
           p.category_name,
           oi.quantity * oi.sale_price as gross_amount,
           isnull((
               select sum(rf.refund_amount)
               from bi_refund as rf
               where rf.order_item_id = oi.order_item_id
                 and rf.refund_status = 'success'
           ), 0) as refund_amount
    from bi_sales_order as o
    join bi_sales_order_item as oi
      on oi.order_id = o.order_id
    join dim_product as p
      on p.product_id = oi.product_id
    join dim_customer as c
      on c.customer_id = o.customer_id
    join dim_region as r
      on r.region_id = c.region_id
    where o.order_status = 'paid'
      and o.pay_time >= @begin_time
      and o.pay_time <  @end_time
) as q
group by q.region_name,
         q.category_name
order by q.region_name,
         q.category_name;

这类 sql 的麻烦不在行数多,而在执行路径容易变长。订单先与明细、商品、客户和区域关联,退款标量子查询再按外层 order_item_id 取值,最外层完成区域和分类汇总。数据量和并发上来以后,退款表的访问次数、连接顺序以及中间结果规模都会影响响应时间。

先保持业务语义,再做集合化改写

迁入 kingbasees 后,第一版 sql 只做必要的语法适配。isnull 改为 coalesce,时间边界使用 timestamp 字面量,其他关联和聚合口径保持不变。这样得到的结果可以与 sql server 基线逐项对照。

with order_summary as (
    select o.order_id,
           oi.order_item_id,
           r.region_name,
           p.category_name,
           oi.quantity * oi.sale_price as gross_amount,
           coalesce((
               select sum(rf.refund_amount)
               from bi_refund as rf
               where rf.order_item_id = oi.order_item_id
                 and rf.refund_status = 'success'
           ), 0) as refund_amount
    from bi_sales_order as o
    join bi_sales_order_item as oi
      on oi.order_id = o.order_id
    join dim_product as p
      on p.product_id = oi.product_id
    join dim_customer as c
      on c.customer_id = o.customer_id
    join dim_region as r
      on r.region_id = c.region_id
    where o.order_status = 'paid'
      and o.pay_time >= timestamp '2026-07-01 00:00:00'
      and o.pay_time <  timestamp '2026-07-02 00:00:00'
)
select region_name,
       category_name,
       count(distinct order_id)         as order_count,
       sum(gross_amount)                as gross_amount,
       sum(refund_amount)               as refund_amount,
       sum(gross_amount - refund_amount) as net_amount
from order_summary
group by region_name,
         category_name
order by region_name,
         category_name;

结果核对完成后,退款计算改成按订单明细预聚合。原来嵌在明细结果中的标量子查询被展开为独立集合,优化器可以在退款汇总结果和订单明细之间选择更合适的连接路径,也避免同一明细行重复触发退款访问。

with refund_agg as (
    select order_item_id,
           sum(refund_amount) as refund_amount
    from bi_refund
    where refund_status = 'success'
    group by order_item_id
),
order_detail as (
    select o.order_id,
           oi.order_item_id,
           r.region_name,
           p.category_name,
           oi.quantity * oi.sale_price as gross_amount,
           coalesce(ra.refund_amount, 0) as refund_amount
    from bi_sales_order as o
    join bi_sales_order_item as oi
      on oi.order_id = o.order_id
    join dim_product as p
      on p.product_id = oi.product_id
    join dim_customer as c
      on c.customer_id = o.customer_id
    join dim_region as r
      on r.region_id = c.region_id
    left join refund_agg as ra
      on ra.order_item_id = oi.order_item_id
    where o.order_status = 'paid'
      and o.pay_time >= timestamp '2026-07-01 00:00:00'
      and o.pay_time <  timestamp '2026-07-02 00:00:00'
)
select region_name,
       category_name,
       count(distinct order_id) as order_count,
       sum(gross_amount) as gross_amount,
       sum(refund_amount) as refund_amount,
       sum(gross_amount - refund_amount) as net_amount
from order_detail
group by region_name,
         category_name
order by region_name,
         category_name;

改写前后都必须返回相同的区域、分类、订单数、销售金额、退款金额和净额。可以把两端结果导入两张验收表,通过双向差集和金额差异检查确认业务口径没有变化。

select region_name, category_name, order_count,
       gross_amount, refund_amount, net_amount
from verify_report_sqlserver
except
select region_name, category_name, order_count,
       gross_amount, refund_amount, net_amount
from verify_report_kingbase;

select region_name, category_name, order_count,
       gross_amount, refund_amount, net_amount
from verify_report_kingbase
except
select region_name, category_name, order_count,
       gross_amount, refund_amount, net_amount
from verify_report_sqlserver;

两个方向都没有返回记录,才进入性能对比。这样可以避免为了追求耗时下降,误把少算关联、漏算退款或者时间边界变化当成优化成果。

并发测试也按同一条查询口径执行。请求参数固定为同一个报表日期,连接数固定为 100,返回列不随数据库切换改变;压测客户端只记录成功请求,不把连接失败、语法错误或结果集为空的请求算成 tps。平均响应时间之外,还需要关注 p95 和错误率,避免平均值很好看,少量慢请求却一直拖住报表页面。

执行计划、索引和统计信息一起核对

同一条复杂 sql 在两种数据库上的计划节点名称可能不同,验收时没有必要逐字对应,更应该关注扫描范围、连接顺序、标量子查询执行次数、中间结果行数和排序聚合开销。

kingbasees 可以使用执行计划分析最终查询。analyze 会实际执行 sql,buffers 可以补充缓存访问情况,适合在测试环境核对,生产环境使用前仍需评估查询开销。

explain (analyze, buffers)
with refund_agg as (
    select order_item_id,
           sum(refund_amount) as refund_amount
    from bi_refund
    where refund_status = 'success'
    group by order_item_id
)
select o.order_id,
       oi.order_item_id,
       coalesce(ra.refund_amount, 0) as refund_amount
from bi_sales_order as o
join bi_sales_order_item as oi
  on oi.order_id = o.order_id
left join refund_agg as ra
  on ra.order_item_id = oi.order_item_id
where o.order_status = 'paid'
  and o.pay_time >= timestamp '2026-07-01 00:00:00'
  and o.pay_time <  timestamp '2026-07-02 00:00:00';

索引没有追求“越多越好”,而是围绕报表的过滤和关联路径设置。订单表先按状态和支付时间缩小范围,订单与明细通过 order_id 关联,退款再通过 order_item_id 对应到具体商品明细。

create index idx_bi_order_status_pay_time
    on bi_sales_order (order_status, pay_time, customer_id, order_id);

create index idx_bi_order_item_order_product
    on bi_sales_order_item (order_id, product_id, order_item_id);

create index idx_bi_refund_status_item
    on bi_refund (refund_status, order_item_id);

analyze bi_sales_order;
analyze bi_sales_order_item;
analyze bi_refund;
analyze dim_customer;
analyze dim_region;
analyze dim_product;

具体列顺序仍应以数据分布和执行计划为准。这里的组合对应当前报表:order_status 是等值条件,pay_time 是范围条件,order_id 连接订单与明细,order_item_id 连接明细与退款。统计信息刷新后再观察估算行数与实际行数的差距,能够减少迁移初期因统计信息不足造成的计划波动。

左侧查询路径保留了相关标量子查询和多层汇总的特征,右侧把退款数据先按订单明细聚合,再与订单明细结果连接。图中表达的是 sql 结构和验收关注点,并非某次控制台执行计划的复刻;实际判断仍以 kingbasees 返回的计划、行数和耗时为准。

100 并发下,性能差异才真正显现

单会话测试只能发现明显的全表扫描或语法问题。bi 报表上线后,同一个分析页面可能被多个部门同时打开,数据库还要承接其他查询。此次验收把复杂查询放到 100 并发下对比,并统一业务数据、统计时间窗、返回字段和结果集口径。

由于现有材料没有给出服务器型号和绝对耗时,性能数据采用迁移前归一化值,避免补写不存在的毫秒数:

指标sql server 迁移前kingbasees v9r4c019对比结果
复杂查询 tps1.001.60提升 60%
平均响应时间1.000.10约为原来的 1/10
并发数100100口径一致

tps 上升意味着同一时间内可以完成更多报表查询,响应时间下降则直接改变了前端等待体验。原先容易出现长时间等待的经营分析报表,迁移后能够更快返回,业务人员不必为了同一张报表反复刷新页面。

这组数字属于该业务查询、该数据规模和该并发模型下的迁移验收结果,不能直接替代其他系统的容量评估。它能够确认的是:sql server 数据迁移到 kingbasees 后,复杂 bi 查询并没有停留在“语法可执行”的层面;在结果一致、索引匹配和统计信息完整的条件下,v9r4c019 承接了包含标量子查询与多表关联的实际分析负载,并取得了更好的并发表现。

性能变化还需要回到 sql 本身解释。第一版兼容 sql 保留了相关子查询,便于核对迁移前后的语义;经过结果集确认后,热点报表采用按订单明细预聚合的写法,减少重复访问退款表。这个调整没有改变报表的统计含义,却让连接关系和聚合边界更清楚。索引与统计信息的处理同样如此:索引服务于时间过滤和明细关联,统计信息帮助优化器估算实际行数,二者都需要通过计划和并发结果验证,不能仅凭 ddl 是否执行成功来判断效果。

性能验收要留住可复查的证据

数据库迁移上线前,兼容率、对象数量和数据行数都比较容易形成清单,性能却常被一句“测试过了”带过。复杂查询最好至少保留原始 sql、迁移后 sql、结果差异、执行计划和并发指标五类材料。后续数据量增长或报表逻辑调整时,可以沿着同一口径重新验证,而不是重新猜测问题出在哪里。

这次 bi 查询的改善来自几项具体工作共同作用:迁移后的查询保持了原有业务语义,相关标量子查询被转换成可统一优化的集合运算,索引覆盖了时间过滤和订单关联路径,统计信息也在压测前完成刷新。kingbasees v9r4c019 最终交付的不只是迁移工具中的“成功”状态,而是一套能够继续承接高并发报表的查询环境。

对 sql server 数据迁移项目来说,表能查、程序能连只是切换条件;复杂 sql 的结果不变,高并发下响应稳定,业务人员打开报表时不再长时间等待,迁移才真正进入可交付状态。

到此这篇关于sql server迁移kingbasees:复杂bi查询的性能测试和验收的文章就介绍到这了,更多相关sql server迁移kingbasees后的性能验收内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com