SQL Server 中处理大数据量的批量插入时,性能和资源消耗是关键问题。如果直接用 INSERT ... VALUES ... 一条条插入,速度会非常慢,尤其是数据量达到百万级以上时。因此需要结合批量导入机制和优化手段来提升效率。下面从常见方法和优化角度来说明:

一、常见的批量插入方法

  1. BULK INSERT 命令
    • 直接将外部文件(CSV、TXT 等)快速导入表中。
    • 语法简单,速度快,适合大文件导入。
  2. bcp 工具 (Bulk Copy Program)
    • SQL Server 自带的命令行工具。
    • 适合超大数据量的导入导出场景,效率极高。
  3. OPENROWSET(BULK...)
    • 通过 T-SQL 调用外部文件数据源。
    • 可结合 INSERT INTO ... SELECT 使用。
  4. SqlBulkCopy.NET 程序)
    • 在应用程序层面批量插入数据到 SQL Server。
    • 支持映射、批量大小设置,灵活性高。
  5. INSERT INTO ... SELECT 批量写入
    • 当数据已在数据库中(如 staging 表),可以直接批量迁移。

二、批量插入的优化手段

  1. 控制批次大小
    • 一次性插入几百万行容易引发日志膨胀和内存压力。
    • 建议分批插入,比如 每批 1万~5万行,具体取决于硬件和事务日志大小。
  2. 禁用或延迟索引和约束
    • 插入过程中,索引维护会拖慢速度。
    • 可以先 禁用非聚集索引 或删除,插入完成后再重建。
    • 同时可以 关闭外键检查、触发器,批量插入完成后再开启。
  3. 使用最小日志模式 (Minimal Logging)
    • SIMPLEBULK_LOGGED 恢复模式下,批量操作可以减少日志量。
    • BULK INSERTSELECT INTOINSERT ... WITH (TABLOCK) 都能触发最小日志。
    • 注意:需要目标表为空或没有非聚集索引时效果最好。
  4. 使用表锁而非行锁
    • INSERT 时加 TABLOCK 提示,减少锁开销。
    • 例: INSERT INTO TargetTable WITH (TABLOCK) SELECT * FROM SourceTable;
  5. 合理设置事务
    • 大事务会占满日志文件。
    • 建议分批提交事务(例如每插入 5万行提交一次)。
  6. 调优磁盘与日志文件
    • 预先扩大事务日志文件,避免插入过程中频繁扩展。
    • 使用快速存储(SSD/NVMe),提升 IO 性能。
  7. 表分区 (Partitioning)
    • 对特别大的表,可以先导入到分区,再通过切换分区(ALTER TABLE SWITCH)实现快速上线。
  8. 并行处理
    • 可以在应用层或 ETL 工具中 多线程分区写入,充分利用多核 CPU。

三、推荐实战方案

  • 超大文件导入:优先用 BULK INSERTbcp,配合 TABLOCKBULK_LOGGED 模式。
  • 应用程序批量插入:用 .NET SqlBulkCopy,设定合适批次大小(如 5000 行/批)。
  • 已在库内的数据迁移:用 INSERT INTO ... SELECT,分批执行,禁用索引,最后重建索引。