我有一个插入查询,它是这样生成的
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 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
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中实现这一点。
非常感谢我得到的所有建议。
如果我以后要进行此类从数据库到数据库的转换,我一定会首先考虑使用BULK INSERT。它似乎更加灵活和快速。