如何用C#在Oracle/Sql Server间高效复制超大规模数据集?
解决3亿行数据跨表复制的内存溢出问题:数据库原生复制方案
核心思路
不用在C#应用层加载任何数据,直接利用数据库的原生跨表/跨库复制能力,让数据库内部完成数据传输,C#仅作为SQL指令的触发方。这种方式完全避免内存占用过高的问题,复制速度也远快于应用层批量处理。
针对SQL Server的实现方案
1. 自动创建目标表并全量复制(目标表不存在时)
如果目标表尚未创建,可通过SELECT INTO语句一步完成表创建和数据复制:
using (var targetConn = new SqlConnection(targetConnectionString)) { targetConn.Open(); var copyCmd = new SqlCommand(@" -- 同库复制 SELECT * INTO dbo.TargetTable FROM dbo.SourceTable; -- 跨库复制(源库和目标库在同一服务器) -- SELECT * INTO TargetDB.dbo.TargetTable FROM SourceDB.dbo.SourceTable;", targetConn); copyCmd.ExecuteNonQuery(); }
2. 兼容目标表已存在的场景
如果目标表可能已存在,可先判断表是否存在,不存在则创建,存在则清空后全量复制:
using (var targetConn = new SqlConnection(targetConnectionString)) { targetConn.Open(); var copyCmd = new SqlCommand(@" IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'TargetTable' AND schema_id = SCHEMA_ID('dbo')) BEGIN SELECT * INTO dbo.TargetTable FROM SourceDB.dbo.SourceTable; END ELSE BEGIN TRUNCATE TABLE dbo.TargetTable; INSERT INTO dbo.TargetTable SELECT * FROM SourceDB.dbo.SourceTable; END", targetConn); copyCmd.ExecuteNonQuery(); }
3. 跨服务器复制(Linked Server)
如果源和目标在不同服务器,可先在SQL Server中配置链接服务器,然后直接执行跨服务器复制:
using (var targetConn = new SqlConnection(targetConnectionString)) { targetConn.Open(); var copyCmd = new SqlCommand(@" SELECT * INTO dbo.TargetTable FROM [LinkedSourceServer].SourceDB.dbo.SourceTable;", targetConn); copyCmd.ExecuteNonQuery(); }
针对MySQL的实现方案
MySQL可通过CREATE TABLE ... LIKE先同步表结构,再用INSERT INTO ... SELECT复制数据:
using (var conn = new MySqlConnection(connectionString)) { conn.Open(); var copyCmd = new MySqlCommand(@" CREATE TABLE IF NOT EXISTS TargetTable LIKE SourceTable; TRUNCATE TABLE TargetTable; INSERT INTO TargetTable SELECT * FROM SourceTable;", conn); copyCmd.ExecuteNonQuery(); }
方案优势
- 零应用层内存占用:所有数据操作都在数据库内部完成,C#无需加载任何数据到内存,彻底解决
Out of Memory Exception。 - 复制速度更快:数据库内部的数据传输效率远高于应用层的批量读写,尤其针对亿级数据量,速度提升明显。
- 代码更简洁:无需编写复杂的批次读取、批量插入逻辑,仅需执行几条SQL指令。
内容的提问来源于stack exchange,提问作者Shishank Jha
相关产品推荐
相关产品推荐

