每秒插入30,000条数据到SQL的最佳方法是什么?

3
不使用SSIS、批量插入、批量加载或任何批量操作;我需要能够调用存储过程来插入数据。
我有一个包含超过1800万条记录的2.8 GB文件。我的解决方案采用C#编写,并利用并行处理和ASYNC-AWAIT,在多个服务器上使用多线程进程来解析这个文件,只需10分钟。然而,无论我尝试什么,增加线程、增加服务器,甚至传递一个表值参数以在一次调用中插入多个记录,我能将这些记录最快地插入SQL数据库的速度是每秒3100条。存储过程只包含INSERT语句,表没有索引或键。以这种速度,将解析结果存储到数据库中需要100分钟。我需要将此时间缩短到10分钟,这意味着我必须将插入记录的能力提高十倍。数据库是我的唯一瓶颈。
A)使用多个文件组有用吗?
B)将表分成不同版本,例如:EtlRecords001,EtlRecords002,EtlRecords003,...,EtlRecords100。这里的想法是使表更小。
C)最后,通过使用多个SQL服务器扩展工作。这里的想法也是使用较小的表,结合使用几个数据库服务器。
对于B和C的情况,显然解决方案需要在不同的机器上针对不同的B)表版本;C)服务器实例。
由于我对文件组知之甚少,因此我相信有比案例B和C更好的方法。
最后,购买一个具有128 GB RAM和48个核心的服务器对我来说不是可行的选择 :)

在上传过程中,CPU、硬盘或内存是否达到峰值? - Ray Krungkaew
Rawitas,我没有远程登录数据库服务器的权限,所以无法回答这个问题。无论如何,这个服务器上有超过30个其他数据库,我不知道企业中的其他应用程序如何使用这些数据库。占用资源真的不是一个选项,所以我需要能够在不使CPU、硬盘或内存峰值的情况下解决这个问题。然而,在其他服务器上添加表、文件组,甚至创建新的数据库是我有权限做的事情。 - Paul Rivera
通过使用活动监视器,我可以看到有很多等待任务;我看到峰值超过60。 - Paul Rivera
1个回答

0

你能试着把数据分成批处理吗?因为你无法测量计算资源的瓶颈。我最好的猜测是你的内存是瓶颈。

create cursor ....
select YEAR(timestamp)-- or anything else

while ....
    insert into table1(...)
    select * from whatever 
    where YEAR(timestamp) = year
end

第二点 exec dbo.insert1 with recompile 你可能需要重新编译存储过程,以便在每次调用时获得适合数据大小的新计划。


我已经将数据分成了批次,这就是我能够在10分钟内解析2.8GB文件的方法。换句话说,当我注释掉我的数据层代码时,各个机器上的跟踪日志显示已成功解析了1800万条记录,并且整个过程在10分钟内完成。当我取消注释我的数据层调用时,跟踪代码揭示了瓶颈。所有的1800万条记录都被成功地插入到数据库中,但这次过程花费了一小时四十二分钟。 - Paul Rivera
你能否以某种方式获取查询计划?你可以尝试使用重新编译的存储过程吗? - Ray Krungkaew
这是一个简单的插入语句,用于向一个有7列的表中插入数据。没有视图、主键、约束、索引、默认值,我也没有使用任何提示、公共表达式或逻辑语句,只是一个基本的插入语句。 - Paul Rivera
执行计划与资源分配有关,因此有时使用重新编译的存储过程可以帮助解决问题。 - Ray Krungkaew
一直在研究使用“with recompile”;我会尝试并报告任何性能提升。谢谢! - Paul Rivera
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接