19

我正在将文本文件中的大量数据加载到 SQL Server 中。目前,每条记录都在单独的事务中插入(或更新),但是如果记录失败,这会使数据库处于错误状态。

我想把这一切都放在一笔大交易中。就我而言,我正在查看约 250,000 个插入或更新,可能还有约 1,000,000 个查询。文本文件大约 60MB。

将整个操作放在一个事务中是否不合理?限制因素是什么?

4

4 回答 4

18

这样做不仅不是不合理的,而且如果你想在任何记录失败的情况下保持完整性,这是必须的,所以你会得到一个“全有或全无”的导入,就像你注意到的那样。SQL 可以处理 250000 次插入或更新,但我会看看这百万次查询是什么。如果不需要它们来执行数据修改,我会将它们从事务中取出,这样它们就不会减慢整个过程。

您必须考虑到,当您有一个打开的事务(无论大小)时,会在它所接触的表上发生查找,并且像您这样的冗长事务可能会导致其他试图同时读取它们的用户阻塞。如果您预计导入会很大且耗时并且系统将处于负载状态,请考虑在夜间(或任何非高峰时段)执行整个过程以减轻影响。

关于大小,SQL Server 没有具体的大小限制,理论上可以修改任意数量的数据没有问题。实际限制实际上是目标数据库的事务日志文件的大小。数据库引擎在事务进行时将所有临时和修改的数据存储在此文件中(因此如果需要,它可以使用它来回滚它),因此此文件的大小会增长。它必须在 DB 属性中有足够的可用空间,以及足够的 HD 空间以使文件增长。此外,引擎将在受影响表上放置的行或表锁会消耗内存,因此服务器也必须有足够的空闲内存来完成所有这些管道。无论如何,60MB 的大小通常太少而无需担心。250,000 行是可观的,但也不算多,因此任何体面大小的服务器都可以处理它。

于 2013-07-09T20:13:17.947 回答
3

SQL Server 可以处理这些大小的事务。我们使用单个事务批量加载数百万条记录。

数据库操作中最昂贵的部分通常是客户端服务器连接和流量。对于插入/更新,索引和日志记录也很昂贵,但您可以通过使用正确的加载技术来降低这些成本(见下文)。您确实想限制客户端和服务器之间传输的连接和数据量。

为此,您应该考虑使用带有 SqlBulkCopy 的 SSIS 或 C# 批量加载数据。批量加载所有内容后,您可以在服务器上使用基于集合的操作来更新或验证您的数据。

查看此问题以获取有关优化数据加载的更多建议。这个问题与 C# 有关,但很多信息对 SSIS 或其他加载方法很有用。在 SQL Server(C# 客户端)中批量插入大量数据的最快方法是什么

于 2013-07-09T20:33:14.637 回答
0

进行全有或全无批量操作没有问题,除非完全回滚对您的业务有问题。事实上,单个事务是许多批量插入实用程序的默认行为。

我强烈建议不要每行进行一次操作。如果要清除不良数据,可以先将数据加载到临时表中,然后以编程方式确定“不良数据”并跳过这些行。

于 2013-07-09T20:21:00.513 回答
-1

就个人而言,我从来没有将导入的数据直接加载到我的 prod 表中,并且在我到达加载点之前,我清除了所有不会通过集合的记录。某些类型的错误会完全终止导入,而其他错误可能只是将记录发送到异常表以发送回提供者并为下一次加载进行修复。通常我有逻辑来确定是否有太多异常并杀死包。

例如,假设城市是您数据库中的一个必需字段,并且在包含 1,000,000 条记录的文件中,您有十个没有城市。最好将它们发送到异常表并加载其余部分。但是假设您有 357,894 条没有城市的记录。然后,您可能需要与数据提供者进行对话,以便在加载之前修复数据。如果您可以在尝试影响生产表之前确定该文件不可用,它肯定会减少对 prod 的影响。

另外,你为什么一次做一张唱片?使用基于集合的处理通常可以更快,特别是如果您已经设法事先清理数据。现在你可能仍然需要分批做,但是一次一个记录可能会很慢。

如果您真的想在任何部分错误时回滚整个事情,是的,您需要使用事务。如果您在 SSIS 中执行此操作,那么您可以仅将事务放在影响 prod 表的包部分上,而不必担心它们在数据的暂存和清理部分中。

于 2013-07-09T20:07:21.917 回答