Jos*_*ose 19 sql-server bulkinsert insert
我有一个像这样生成的插入查询
INSERT INTO InvoiceDetail (LegacyId,InvoiceId,DetailTypeId,Fee,FeeTax,Investigatorid,SalespersonId,CreateDate,CreatedById,IsChargeBack,Expense,RepoAgentId,PayeeName,ExpensePaymentId,AdjustDetailId)
VALUES(1,1,2,1500.0000,0.0000,163,1002,'11/30/2001 12:00:00 AM',1116,0,550.0000,850,NULL,@ExpensePay1,NULL);
DECLARE @InvDetail1 INT; SET @InvDetail1 = (SELECT @@IDENTITY);
Run Code Online (Sandbox Code Playgroud)
仅为110K行生成此查询.
所有这些查询都需要30分钟才能执行
我检查了查询计划,最大的%节点是
群集索引以57%的查询成本插入,其中包含一个我不想发布的长xml.
表Spool,查询成本为38%
<RelOp AvgRowSize="35" EstimateCPU="5.01038E-05" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimateRows="1" LogicalOp="Eager Spool" NodeId="80" Parallel="false" PhysicalOp="Table Spool" EstimatedTotalSubtreeCost="0.0466109">
<OutputList>
<ColumnReference Database="[SkipPro]" Schema="[dbo]" Table="[InvoiceDetail]" Column="InvoiceId" />
<ColumnReference Database="[SkipPro]" Schema="[dbo]" Table="[InvoiceDetail]" Column="InvestigatorId" />
<ColumnReference Column="Expr1054" />
<ColumnReference Column="Expr1055" />
</OutputList>
<Spool PrimaryNodeId="3" />
</RelOp>
Run Code Online (Sandbox Code Playgroud)
所以我的问题是我能做些什么来提高这件事的速度?我已经运行了ALTER TABLE TABLENAME NOCHECK CONSTRAINTS ALL在查询之前然后在查询之后ALTER TABLE TABLENAME NOCHECK CONSTRAINTS ALL.
这并没有消除任何时间的任何东西.
知道我在使用SqlCommand对象发送查询的.NET应用程序中运行这些查询.
然后我尝试将sql命令输出到一个文件,然后使用sqlcmd执行它,但我没有得到任何关于它如何做的更新,所以我放弃了.
任何想法或提示或帮助?
更新:
好的,所以你们都非常乐于助人.在这种情况下,我希望我能够赞扬不止一个答案.
解决这个问题的解决方案是双重的.
首先:
1)我禁用/重新启用所有外键(比丢弃它们容易得多)
ALTER TABLE TableName NOCHECK CONSTRAINT ALL
ALTER TABLE TableName CHECK CONSTRAINT ALL
Run Code Online (Sandbox Code Playgroud)
2)我禁用/重新启用索引(再次比丢弃更容易)
ALTER INDEX [IX_InvoiceDetail_1] ON [dbo].[InvoiceDetail] DISABLE
ALTER INDEX [IX_InvoiceDetail_1] ON [dbo].[InvoiceDetail] REBUILD PARTITION = ALL WITH ( PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, ONLINE = OFF, SORT_IN_TEMPDB = OFF )
Run Code Online (Sandbox Code Playgroud)
第二:
我将所有insert语句包装到一个事务中.我最初不知道如何在.NET中这样做.
我非常感谢我得到的所有输入.
如果我从DB到DB进行这种翻译,我一定会从BULK INSERT开始.它似乎更灵活,更快捷.
Pat*_*ick 10
您是从.Net客户端一次执行这些查询(即向SQL Server发送110,000个单独的查询请求)吗?
在这种情况下,可能是网络延迟和将这些INSERT发送到SQL Server而不进行批处理而不是SQL Server本身的其他开销.
查看BULK INSERT.
最有可能的是提交刷新等待.如果不将INSERT集合包装到显式管理的事务中,那么每个INSERT都是它自己的自动提交事务.这意味着每个INSERT会自动发出提交,并且提交必须等到日志持久(即写入磁盘).每次插入后刷新日志非常慢.
例如,尝试在单行提交样式中插入与您类似的100k行:
set nocount on;
declare @start datetime = getutcdate();
declare @i int = 0;
while @i < 100000
begin
INSERT INTO InvoiceDetail (
LegacyId,InvoiceId,DetailTypeId,Fee,
FeeTax,Investigatorid,SalespersonId,
CreateDate,CreatedById,IsChargeBack,
Expense,RepoAgentId,PayeeName,ExpensePaymentId,
AdjustDetailId)
VALUES(1,1,2,1500.0000,0.0000,163,1002,
'11/30/2001 12:00:00 AM',
1116,0,550.0000,850,NULL,1,NULL);
set @i = @i+1;
end
select datediff(ms, @start, getutcdate());
Run Code Online (Sandbox Code Playgroud)
这在我的服务器上运行大约12秒.但是添加事务管理并提交每1000行,100k行的插入只持续大约4s:
set nocount on;
declare @start datetime = getutcdate();
declare @i int = 0;
begin transaction
while @i < 100000
begin
INSERT INTO InvoiceDetail (
LegacyId,InvoiceId,DetailTypeId,
Fee,FeeTax,Investigatorid,
SalespersonId,CreateDate,CreatedById,
IsChargeBack,Expense,RepoAgentId,
PayeeName,ExpensePaymentId,AdjustDetailId)
VALUES(1,1,2,1500.0000,0.0000,163,1002,
'11/30/2001 12:00:00 AM',
1116,0,550.0000,850,NULL,1,NULL);
set @i = @i+1;
if (@i%1000 = 0)
begin
commit
begin transaction
end
end
commit;
select datediff(ms, @start, getutcdate());
Run Code Online (Sandbox Code Playgroud)
另外,即使没有批量提交,我也可以在12秒内插入100k行,而你需要30分钟,值得研究1)IO子系统的速度(例如Avg. Sec per Transaction
你在驱动器上看到的)和2)什么else是从一次调用中检索@@ identity并调用下一个插入之间的客户端代码.可能是大部分时间都在堆栈的客户端.一个简单的解决方案是并行启动多个插入(BeginExecuteNonQuery),以便不断地提供SQL Server插入.
您可以执行以下几项操作:
1) Disable any triggers on this table
2) Drop all indexes
3) Drop all foreign keys
4) Disable any check constraints
Run Code Online (Sandbox Code Playgroud)
运行单个 INSERT 总是最慢的选择。另外 - 与@@IDENTITY 有什么关系 - 看起来你不需要跟踪它们之间的那些。
如果您不想从文件或 SSIS 使用 BULK INSERT,则ADO.NET 中有一个SqlBulkCopy 功能,如果您绝对必须从 .NET 程序中执行此操作,这可能是您最好的选择。
导入 110k 行应该比我研究和编写这个答案花费的时间更少。
归档时间: |
|
查看次数: |
45444 次 |
最近记录: |