insert-select语句是否庞大?

时间:2011-02-23 16:28:52

标签: sql-server select insert commit

当多个插入与事务中的select语句一起使用时,数据库如何跟踪事务期间的更改?如果交易持有太长时间,资源(例如内存或硬盘空间)是否会出现问题?

3 个答案:

答案 0 :(得分:1)

简短的回答是,这取决于选择的大小。从技术上讲,select是事务的一部分,但大多数选择不必“回滚”,因此DB更改的实际日志不包括select本身。它将包含的是select语句的每个结果的新行作为insert语句。如果select语句是10k行,则提交将相当大,但不会超过在显式事务中编写10k个单独的insert语句。

答案 1 :(得分:1)

这究竟是如何工作的取决于数据库。例如,在Oracle中,它将需要UNDO空间(最终,如果你用完了,你的事务将被中止,或者你的DBA会对你大吼大叫)。在PostgreSQL中,它会阻止旧行版本的清空。在MySQL / InnoDB中,它将使用回滚空间,并可能导致锁定超时。

数据库必须使用以下几个空间:

  1. 存储事务已更改的行(旧值,新值或两者)以便可以执行回滚
  2. 跟踪事务中可见的数据,以便维护一致的视图(在未提交的读取之外的事务隔离级别中)。您要求的隔离越多,这种开销通常越大。
  3. 跟踪其他事务可见的数据(除非整个数据库以未提交的方式运行)
  4. 跟踪哪些对象发生了更改,因此遵循隔离规则,尤其是在可序列化隔离中。 (可能没有多少空间,但有很多锁)。
  5. 通常,您希望您的交易尽快提交。因此,例如,您不希望在空闲连接上保持一个打开状态。如何最佳批量插入取决于数据库(通常,一个事务上的许多插入优于每个插入一个事务)。当然,交易的主要目的是数据完整性。

答案 2 :(得分:0)

大型交易可能会遇到很多问题。首先,在大多数数据库中,您不希望逐行运行,因为一百万条记录需要数小时。但是,在一个复杂的语句中插入一百万条记录会导致锁定所涉及的表并损害其他人的性能。如果您终止交易,回滚也可能需要很长时间。通常最好的选择是批量循环。我通常一次测试50,000个并根据需要多长时间来升高或降低设置。我有一些数据库,我在一个基于集合的操作中不会超过1000。如果可能,应安排在数据库运行的非高峰时段进行大量插入或更新。如果真的很大(一次性 - 通常是大型数据迁移),您甚至可能希望关闭数据库进行维护,将其置于单用户模式并删除索引,执行insert和reindex。