【发布时间】:2012-04-28 01:42:57
【问题描述】:
我有一个像这样生成的插入查询
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);
此查询仅针对 110K 行生成。
执行所有这些查询需要 30 分钟
我检查了查询计划,最大的 % 节点是
以 57% 的查询成本插入聚集索引 其中有一个我不想发布的长 xml。
查询成本为 38% 的 Table Spool
<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>
所以我的问题是我可以做些什么来提高这件事的速度?我已经跑了 ALTER TABLE TABLENAME NOCHECK 约束所有 在查询之前然后 ALTER TABLE TABLENAME NOCHECK 约束所有 在查询之后。
这并没有减少任何时间。
知道我正在使用 SqlCommand 对象发送查询的 .NET 应用程序中运行这些查询。
然后我尝试将 sql 命令输出到一个文件,然后使用 sqlcmd 执行它,但我没有得到任何关于它如何做的更新,所以我放弃了。
有什么想法、提示或帮助吗?
更新:
好的,你们所有人都非常有帮助。在这种情况下,我希望我可以将多个答案归功于多个答案。
解决此问题的方法有两个。
第一个:
1) 我禁用/重新启用了所有外键(比删除它们容易得多)
ALTER TABLE TableName NOCHECK CONSTRAINT ALL
ALTER TABLE TableName CHECK CONSTRAINT ALL
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 )
第二个:
我将所有插入语句包装到一个事务中。我最初不知道如何在 .NET 中做到这一点。
我非常感谢我收到的所有意见。
如果我曾经进行这种从 DB 到 DB 的翻译,我肯定会从 BULK INSERT 开始。它似乎更加灵活和快速。
【问题讨论】:
-
告诉我们更多关于您的聚集索引和插入的信息。您的插入是否与您的聚集索引相关,以便所有记录都将附加在现有记录之后? (即,记录与聚集索引自然顺序排列)
-
永远不要使用@@Identity!你可以用这个来搞乱数据完整性,因为它并不总是返回正确的值。请改用 scope_Identity()。
-
我知道这已经过时了,但您还记得最终查询花费了多少时间吗?只是想知道这一切有多大不同?
标签: sql-server insert bulkinsert