SqlBulkCopy必须显式设置BatchSize、DestinationTableName、EnableStreaming三参数,否则千万级插入大概率失败或极慢;BatchSize宜设10000,DestinationTableName须用三段式如"dbo.MyTable",EnableStreaming=true启用流式读取防OOM。

SqlBulkCopy 必须显式设置的三个参数
不设 BatchSize、DestinationTableName、EnableStreaming,千万级插入大概率失败或极慢。
-
BatchSize = 10000:太小(如 100)触发高频网络往返;太大(如 100000)易引发内存溢出或锁升级。1w 是多数 OLTP 场景实测稳定值 -
DestinationTableName = "dbo.MyTable":必须带 schema,只写"MyTable"会报"Invalid object name 'MyTable'" -
EnableStreaming = true:对DataTable或IDataReader源启用流式读取。不设它,500 万行数据可能直接 OOM
列映射错位导致静默丢数据
SqlBulkCopy 默认按列序匹配(source 第 1 列 → target 第 1 列),不是按列名。源列顺序和目标表不一致时,数据全插反,但不报错。
- 查目标表真实列序:
SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='MyTable' ORDER BY ORDINAL_POSITION - 或显式加映射:
bulkCopy.ColumnMappings.Add("SourceName", "TargetName"),注意大小写和拼写——拼错、漏加、大小写不一致都会让该列变NULL或类型转换失败
BULK INSERT 文件路径与权限陷阱
BULK INSERT 要求 SQL Server 进程能直接访问文件路径,不是你本地能打开就行。
- 文件必须在数据库服务器本地磁盘,或配置了 SQL Server 服务账户有读取权限的 UNC 路径(如
\serversharedata.csv) - 不能用
C:UsersMe...这类用户路径——SQL Server 服务一般以NT SERVICEMSSQLSERVER运行,没权限 - 字段/行分隔符必须严格匹配文件内容:
FIELDTERMINATOR = ','但文件用;分隔?整批失败且错误日志可能不明显
bulk_insert_mappings 不触发 ORM 事件,也不走约束校验
SQLAlchemy 的 bulk_insert_mappings 是纯数据搬运工,性能高,但代价明确。
- 不会调用
@validates、before_insert等 ORM 钩子,所有预处理逻辑得提前做干净 - 不检查数据库默认值、
CHECK约束、外键(除非显式开启return_defaults=True并配好返回逻辑) - 遇到类型不匹配(如字典里传了
"age": "25"字符串而非 int),报错位置常在底层驱动层,堆栈难定位

















