2

解析一些数据并将其插入 .NET 的 3 个表中。使用表值参数传递数据,因为某些插入是 600,000 行。传递对象(不是 DataTables),它们是通过引用传递的(TVP 的性质)。由于插入值一次限制为 1000 行,因此与直接值插入相比获得了 100:1 的增益。在存储过程中,从 TVP 到实际表的插入按聚集索引排序。这些表除了聚集索引之外没有其他索引。SP 采用 TABLOCK,因为它们是一次写入表和一个数据加载器。填充因子 100。数据或事务日志大小没有增加 - 它的大小适合总数据负载。终于到问题了。在过去 4 小时内插入了 2 亿行。插入响应时间减少了 1/2。如果填充因子为 100 并且我插入的是按聚集索引排序的,那么为什么响应下降?我能做些什么来解决这个问题?

在我使用它之前我没有得到 TVP——它就像一个反向 DataReader。

我要感谢您的帮助,并为不正确的问题陈述道歉。对于每个解析(在本例中我解析 200,000),插入按聚集索引排序。然而,对于 3 个表中只有 1 个表是下一个整体以聚集索引顺序进行的解析。解析 70,000 后,好表的扫描密度为 99%,但其他两个表碎片严重,扫描密度为 12%。

在两个碎片表上设置填充因子 50 并重新建立索引。现在我得到了大约 1/3 的最大速度。我只需要每隔几个小时停止该过程并重新索引一次。

我最终做的是更改聚集索引以匹配插入顺序。对曾经聚集的内容创建了唯一索引。我禁用唯一,索引插入数据,然后重建唯一索引。在这种情况下,我在 10 小时的跑步中获得了 300:1 的性能。这不是一个额外的 0 - 三百比一。这不是捏造的 - 与从排序索引和填充因子或 30 开始相比。即使有额外的索引,我的表大小也更小,因为我可以将两个填充因子都设置为 100。

我在某些查询上使用#temp,因此我可以按照只有查询知道的顺序获取行。我将#temp 转换为TVP 并获得了1/2 秒(大约是创建和删除#temp 所需的时间)。

4

1 回答 1

0

每个 OP 将评论转换为答案...

除了@SqlACID 提到的自动统计之外,随着表填满,约束检查可能会变得更加昂贵。如果我要认真加载一个表,我通常计划禁用或删除索引和约束,然后重新创建它们,如果速度是我的最终目标。这可能意味着如果违反了约束,则在事后删除行,或者在可能的情况下预先对批量数据进行更好的验证。

于 2012-03-09T14:41:57.353 回答