【问题标题】:Sql insert query performancesql插入查询性能
【发布时间】:2010-11-15 00:58:40
【问题描述】:

我想在一个表中插入 n 条记录。可能有许多并发用户,他们可能会从该表中插入/更新/选择数据。在这样的表中插入 1000 条记录的更好方法是什么:

  1. 将单个 sql 查询发送到具有多个插入的数据库。这将服务器保存到数据库调用,但(我不确定)锁定表,直到插入完成,并且对该表的所有其他查询都将等待。
  2. 将 1000 条记录分成若干块,并在多个 sql 查询中发送。这允许在表上执行其他查询,但将时间花在服务器到数据库的调用上。

这取决于某些东西,还是只有一种方法始终是最佳方法? 这是否取决于在插入数据时是否使用事务? 还有其他更好的方法来执行此类插入吗?

我使用的数据库是 MS SQL,但有趣的是它在 Oracle 等其他数据库中的工作方式。

【问题讨论】:

    标签: sql database performance insert


    【解决方案1】:

    一般规则是您应该让数据库弄清楚如何完成这项工作。你在一个语句中告诉它做的事情越多,效果越好,即你应该一次性插入 1000 条记录。这对于大多数数据库服务器最有效,并且大多数服务器不会阻止读取写入。

    也有例外:如果插入很慢是因为服务器很慢或者表很大或很复杂,那么可能最好将查询拆分成小插入组。

    一种介于两者之间的方法是向服务器发送多个插入命令,例如 10 或 100 行,并在一个大脚本中将其提交到服务器。

    补充:大多数数据库服务器不会像在 Oracle、IBM DB/2 和 MySQl 中使用 InnoDB 表那样阻塞读取。另一方面,SQL Server 设法锁定表,即使是读取也不在其中。

    【讨论】:

    【解决方案2】:

    这完全取决于您使用的RDBMS

    Oracle 中,写入永远不会阻塞读取,这就是为什么您可以一次安全地放置所有数据的原因。但请注意,这会降低性能,因为并发查询需要从需要额外读取的 UNDO 表空间中提取数据。

    SQL Server 中,写入会阻塞对受影响的行/页/表的读取(取决于锁升级问题),除非您将TRANSACTION ISOLATION LEVEL 设置为SNAPSHOT

    在所有允许并发写入和读取的事务引擎中,引擎需要将新旧数据都存储在某个地方以使其同时可用。

    Oracle 中,旧数据被复制到UNDO 表空间中。

    SQL Server 中,它被复制到tempdb 中(仅当SNAPSHOT 隔离启用时,否则它只是被锁定)。

    这总是需要一些资源(内存或磁盘),如果您的 UPDATE 查询影响大量行,您可能会用完这些资源。

    【讨论】:

      【解决方案3】:

      我在博客上写了这个 a while ago- 我认为这篇文章回答了你的一些问题。如果您担心读者会阻止作者,CK 的建议是合理的(Quassnoi 也是如此——他对 Oracle 有一些好处)。

      【讨论】:

      • 有趣的博文 +1。 reason 交易在您的测试中出现得更快,这激起了我的兴趣。我怀疑这是因为许多必要的锁已经被之前的通道占用了。但是,您的帖子未解决的一个关键问题是负载下的行为。您的测试似乎是孤立的;在实时系统中,我怀疑结果会很快反转。
      【解决方案4】:

      设置允许在事务期间读取旧数据的隔离(并发)级别 - 例如SQL Server 2005+ 已读取快照。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-02-22
        • 2018-11-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多