今天,我处理了一个非常有趣的案例,我们的客户想要使用 Python 插入数百万行。我们审查了两种尽快导入数据的替代方案:使用 BCP 命令行和使用executemany 命令。下面我想分享一下我的经验教训。
背景:
我们有 5 个 CSV 文件,其中包含 111.100.000 和大约 22 列(20 varchar(6) 和 2 int 数据类型列)。
Azure SQL数据库是标准 9
虚拟机:
所有文件都放置在临时驱动器(D:) 上。
加速网络被禁用。
vCore 4 和 16 GB RAM
目标是尽快导入数据。
得到教训:
我开发了两个不同的python 脚本,两者都会读取每个 CSV 文件,但使用两种不同的方法来导入数据:
使用主线程读取每个 CSV。批量大小为 10000。
插入所有数据所花费的时间是在数据库级别:
20分钟
CPU DB 使用率5%-10%
日志 IO 使用率80%-90%
每分钟插入7M 行
由于我发现单个线程会花费太多时间,因此我配置为同时运行 100 个线程。
主线程读取 CSV 文件,当达到 10000 行时,它将该数据数组发送到在后台执行 executemany 的单个线程。我管理了100个线程的状态。
插入所有数据所花费的时间是在数据库级别:
该线程在 TEMPDB 中创建一个时态表
完成后,运行INSERT INTO 到主表。
该主表是一个没有任何非聚集索引的头表。
执行40分钟。
CPU DB 使用率70%-80%
日志IO使用率60%-70%
每分钟插入340 万行。
1)使用executemany方法:
2)调用BCP.exe
很明显,即使当executemany 使用准备好的TSQL 命令来提高性能时,BCP 也更好。我将检查我们是否有像 .NET - SqlBulkCopy中那样的保存选项 ,性能要好得多。