最大限度地减少DataTable / SqlDataAdapter中更改的数据库更新

时间:2009-07-30 13:59:58

标签: c# .net sql-server-2005 performance optimization

我的目标是最大限度地提高绩效。该方案的基础是:

  • 我将SQL Server 2005中的一些数据读入DataTable(1000条记录x 10列)
  • 我在.NET中对数据进行了一些处理,所有记录在DataTable中至少更改了一个字段,但可能会更改所有10个字段
  • 我还在DataTable中添加了一些新记录
  • 我使用SqlDataAdapter.Update(myDataTable.GetChanges())使用我在开始时定义的InsertCommand和UpdateCommand将更新(插入)持久化回数据库
  • 假设正在更新的表包含数百万条记录

这很好。但是,如果DataTable中的行已更改,则即使9列中只有1列实际更改了值,也会在数据库中更新该记录的所有列。这意味着不必要的工作,特别是涉及索引时。我不相信SQL Server会优化这种情况吗?

我认为,如果我只能更新任何给定记录实际更改的列,那么我应该会看到明显的性能提升(特别是累计,我将处理数百万行)。

我找到了这篇文章:http://netcode.ru/dotnet/?lang=&katID=30&skatID=253&artID=6635 但是不喜欢在sproc中做多个UPDATE的想法。 如果没有为每个已更改的DataRow创建单独的UPDATE语句,然后以某种方式批量触发它们,我正在寻找其他人的经验/建议。

(请假设我不能使用触发器)

提前致谢

编辑:有什么方法可以让SqlDataAdapter发送特定于每个已更改的DataRow的UPDATE语句(仅更新该行中实际更改的列),而不是提供更新所有列的常规.UpdateCommand?

3 个答案:

答案 0 :(得分:2)

是否可以在实现此功能的情况下实现自己的IDataAdapter?

当然,DataAdapter只会触发正确的SqlCommand,它由每个DataRow的RowState决定。 所以,这意味着你必须生成必须为每种情况执行的SQL命令......

但是,我想知道这是否值得付出努力。你会获得多少性能?
我认为 - 如果真的有必要 - 我将禁用所有索引和约束,使用常规SqlDataAdapter进行更新,然后启用索引和约束。

答案 1 :(得分:0)

您可能会尝试创建已更改数据集的XML,将其作为参数传递给sproc并使用sql nodes()函数将xml转换为表格形式。

你永远不应该尝试更新聚集索引。如果你这样做是时候重新考虑你的数据库模式。

答案 2 :(得分:0)

我非常建议您使用存储过程执行此操作。 假设您有1000万条记录需要更新。并且假设每个记录有100个字节(对于10个列,这可能太小,但让我们保守)。这相当于cca 100 MB的数据,必须从数据库(网络流量)传输,存储在内存中,然后以UPDATE或INSERT的形式返回到数据库,这些数据更加冗长,无法传输到数据库。

我希望SP会表现得更好。

再次,您可以将工作划分为更小的SP(从主SP调用),它将仅更新必要的字段,并以此方式获得额外的性能。

禁用索引/约束也是一种选择。

编辑:
您必须考虑的另一件事是可能的不同更新语句数。如果每行10个字段,则任何字段都可以保持不变或更改。因此,如果您构造UPDATE语句以反映这一点,您可能会得到10 ^ 2 = 1024个不同的UPDATE语句,其中任何一个必须由SQL Server解析,执行计划计算和解析语句存储在某个区域中。这样做是有代价的。