SSIS中Aggregate ADO.Net源统计结果插入SQL Server的最优方案
10亿行级表当月每日行数统计插入SQL Server最优方案
核心优化逻辑:你统计的是当月每日行数,最终输出最多31条数据,优化重点是减少源表扫描开销、避免不必要的数据跨层流转。
场景1:ADO.NET数据源与目标SQL Server支持跨库查询(同实例/已配置链接服务器)
这是性能最优的方案,所有运算都在数据库引擎层完成,无额外数据传输开销,直接使用INSERT ... SELECT语句即可,你原有语句的INSERT顺序错误,修正后如下:
INSERT INTO dbo.OLEDB_Inegrated (activityDate, RecCount) SELECT g.[ActivityDate], COUNT(*) RecCount FROM [lab10].[ADONETSource_Integrated] g -- 若无特殊业务日期规则,可去掉DimDate关联直接过滤,减少表关联开销 WHERE g.ActivityDate >= DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), 1) -- 可选:如果只统计已结束的日期,避免当天未闭合数据被统计,加下面这行 -- AND g.ActivityDate < CAST(GETDATE() AS DATE) GROUP BY g.[ActivityDate] -- 插入不需要排序,去掉原有ORDER BY减少排序开销
额外优化点:
- 源表
ADONETSource_Integrated的ActivityDate列必须创建非聚集索引,可直接走索引范围扫描,避免10亿行全表扫描,性能提升可达数百倍 - 如果需要避免任务重复执行导致的重复插入,可增加判重逻辑:
INSERT INTO dbo.OLEDB_Inegrated (activityDate, RecCount) SELECT g.[ActivityDate], COUNT(*) RecCount FROM [lab10].[ADONETSource_Integrated] g WHERE g.ActivityDate >= DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), 1) AND NOT EXISTS ( SELECT 1 FROM dbo.OLEDB_Inegrated t WHERE t.activityDate = g.ActivityDate ) GROUP BY g.[ActivityDate]
场景2:ADO.NET数据源无法与目标SQL Server直接跨库查询
方案A:用ETL工具实现
使用SSIS、Azure Data Factory等ETL工具:
- 源配置为ADO.NET数据源,执行你编写的统计查询语句
- 目标配置为SQL Server目标,启用批量插入模式,因为最终结果只有几十行,单次即可完成插入
方案B:自定义代码实现
如果用C#等语言自定义开发,使用SqlBulkCopy类完成批量插入:
- 用ADO.NET从源库查询出统计结果,存入DataTable或者DataReader
- 调用
SqlBulkCopy直接批量写入目标SQL Server,性能远高于逐行执行INSERT语句
通用优化建议
- 如果是每日定时调度任务,不需要每次统计全月数据,只统计前一天的行数即可,进一步缩小源表扫描范围
- 目标表如果有除了ActivityDate之外的非聚集索引,当前数据量下可以忽略优化,若后续统计数据量变大可临时禁用索引,插入完成后再重建
内容的提问来源于stack exchange,提问作者SJJ9166
相关产品推荐
相关产品推荐

