2011-03-16 80 views
6

基本上我有一個兩字段主鍵列(memberid,messageid)的表,我有一個存儲過程插入到該表中的新行。在插入之前檢查主鍵值是否比使用try-catch更快?

現在我檢查是否存在與PK的行,如果沒有,插入,但我已經遇到了情況,當該行被檢查之後和實際插入之前的不同進程插入時,我正在考慮一種替代方法。

我不想爲了性能的原因使用事務,所以我想把INSERT放入try-catch並且完全跳過檢查。如果該行已經存在,插入將會失敗,但會被「catch」無聲,這是可以的。

我的問題是 - 拋出一個錯誤,並使其成爲一個昂貴的操作?

+2

相關:http:// stackoverflow。com/questions/3407857/only-inserted-a-row-if-its-not-already-there – 2011-03-16 20:49:24

+0

你可以在那些具有忽略重複鍵的列上創建一個UNIQUE INDEX,所以你不必在以前檢查,也沒有做'TRY-CATCH' – Lamak 2011-03-16 20:50:20

+0

@Lamar - 根據定義,PK是唯一的。這個事實對我有何幫助? – Andrey 2011-03-16 20:56:26

回答

0

如果您不希望失敗經常發生,那麼可以通過異常來處理失敗。

做檢查,每次會降低分貝性能比較可能影響應用程序的性能比較,以及...

0

是的,拋出異常是一個昂貴的操作。但是,它可能是特定於應用程序的,但吞嚥(沉默,正如你所說的)例外通常不是一個好主意。

+1

您認爲拋出異常很少會比數據庫查詢總是更昂貴嗎? – Gabe 2011-03-16 20:51:00

+0

爲什麼在我的情況下「吞嚥」錯誤是不好的?我確切地知道什麼可以出問題,我確定它會失敗 - 我不能保證在db中沒有給定PK的行,除非我使用交易 – Andrey 2011-03-16 20:51:06

+0

@Gabe - 正是我的觀點!我認爲我的應用程序絆倒這個錯誤的概率低於1%,所以問題幾乎就是拋出一個錯誤比查詢PK 100次還要貴嗎:) – Andrey 2011-03-16 20:52:40

0

如果你不使用交易,你必須考慮的可能性,該行可能會被插入無論如何,所以你不能消除異常處理。充其量,你可以事先做一個查詢來減少罕見的異常。但是,在插入之前執行詢問的成本很可能比偶爾的例外更多。

儘管如此,您必須親自測試才能看到現實生活中更貴的東西。可能的原因是,偶爾出現異常的毫秒數將遠遠低於不斷查詢您即將插入的密鑰的成本。這就是說,你可以使用存儲過程來處理插入,並在插入重複鍵時返回錯誤值,而不是拋出異常。這應該完全消除性能問題。

+0

你是什麼意思「你可以使用存儲過程來處理插入,並在插入重複鍵時返回一個錯誤值,而不是拋出異常,這應該完全消除性能問題。 ?性能問題正在發生,因爲當我插入重複項時會引發錯誤,即使我之後在proc中處理它也是如此。我錯過了什麼嗎? – Andrey 2011-03-21 22:01:20

3

在SQL 2008上,你可以使用MERGE--比任何一種方法都簡單得多。

另外,我不會與您「因爲性能原因不想使用事務」 - 您執行的每個DML命令都是某個事務的一部分,所以即使沒有明確打開它們也會有事務。如果您遇到性能問題,可以發佈更多詳細信息,以便獲得更多性能幫助。

編輯:如果您需要真正快速的插入,請不要一次插入一行。添加行集合,並使用MERGE - 一次插入批次行的優點應遠遠超出通過優化添加一行的速度所帶來的任何微小改進。

無論如何,有關數據庫的任何理論推理通常都不夠好。你真的需要基準來確定什麼更快。你所稱的「不必要地查詢現有的行」可能完全可以忽略不計,並且在實際情況下對其進行測量之前不知道是否是這種情況。

+0

MATCH做了什麼等於:如果存在(...)則更新,否則插入,這正是我想避免的 - 不必要的索引查詢。 – Andrey 2011-03-17 22:02:16

+0

此外,我相信INSERT不會鎖定表中的任何內容,其中運行查詢然後在事務中插入應該鎖定整個表以避免併發性,從而造成巨大的性能下降。 – Andrey 2011-03-17 22:04:57

+1

以下內容顯然是錯誤的:「在事務中插入應鎖定整個表以避免併發」。我建議你運行一些測試,看看實際上被插入鎖定了什麼。 – 2011-03-19 17:57:50

相關問題