2009-07-29 219 views
6

我想插入n個記錄到一個表中。可能有許多併發用戶,他們可能會從該表中插入/更新/選擇數據。在這樣的表格中插入1000條記錄的更好方法是:Sql插入查詢性能

  1. 將單個sql查詢發送到具有多個插入的數據庫。這將服務器保存到數據庫調用,但(我不確定)鎖定表,直到插入完成,並且對此表的所有其他查詢將等待。
  2. 在一些塊中劃分1000條記錄並在多個sql查詢中發送它們。這可以讓其他查詢在表上執行,但花時間在服務器上調用數據庫。

這是取決於某件事情,還是有一種方法總是最優的? 這是否取決於事務是否使用,而插入數據? 還有其他更好的方法來執行這樣的插入嗎?

我使用的數據庫是MS SQL,但它很有趣,它如何在Oracle等其他數據庫中工作。

回答

6

這完全取決於您使用的是什麼RDBMS

Oracle中,寫入從不阻止讀取,這就是爲什麼您可以安全地將您的數據一次全部放入。但請注意,這會降低性能,因爲併發查詢將需要從UNDO表空間中提取數據,這將需要額外的讀取。

SQL Server在受影響的行/頁/表上執行塊讀取(取決於鎖升級問題),除非您將TRANSACTION ISOLATION LEVEL設置爲SNAPSHOT

在允許併發寫入和讀取的所有事務引擎中,引擎需要將舊數據和新數據同時存儲在某處。

Oracle中,舊數據被複制到UNDO表空間中。

SQL Server,它就會被複制到tempdb(僅當啓用SNAPSHOT隔離,否則它只是鎖定)。

這總是需要一些資源(內存或磁盤),並且如果您的UPDATE查詢影響很多行,則可能會用盡這些資源。

1

設置允許在事務期間讀取舊數據的隔離(併發)級別 - 例如, SQL Server 2005+具有READ SNAPSHOT。

2

我在這篇文章a while ago的博客 - 我認爲這篇文章回答了你的一些問題。如果你擔心讀者會阻止作者,CK的建議是合理的(對於Quassnoi-他也有一些關於Oracle的好處)。

+0

有趣的博文+1。這讓我感興趣,因爲在您的測試中_reason_交易顯得更快。我懷疑這是因爲許多必要的鎖已經被事先通過。但是,一個關鍵的問題是,你的帖子沒有解決的是負載下的行爲。你的測試似乎是孤立的;在現場系統中,我懷疑結果會很快反轉。 – EBarr 2011-04-20 18:42:17

2

一般規則是你應該讓數據庫找出如何完成這項工作。如果您在一個聲明中聲明的內容越多,就越好,即您應該一次插入1000條記錄。這對於最適用於大多數數據庫服務器,並且大多數服務器不會阻止讀寫操作。

有例外:如果插入緩慢,因爲服務器速度慢或表大或複雜它可以可能更好地將查詢拆分成小插入組。

一個介於兩者之間的方法可能是發送多個插入命令,例如10或100行,並在一個大腳本與服務器之間進行提交。

增加:大多數數據庫服務器不會像使用InnoDB表的Oracle,IBM DB/2和MySQl那樣阻止讀取。另一方面SQL Server管理甚至爲讀取鎖定表,不在其中。

+1

我想你會發現大多數數據庫都有讀者阻止作者的問題(Oracle不)。 – RichardOD 2009-07-29 12:03:27