2017-07-28 66 views
1

我創造了許多光標在我的應用程序通過行操作中我只選擇了500或1000個記錄每個光標單次運行執行行,以便光標可以完成的循環在單次運行中很快成爲postilion,換句話說,我爲單個遊標運行選擇了有限數量的記錄。SQL服務器 - 雖然與「本地靜態READ_ONLY FORWARD_ONLY」光標

要執行光標更快,而不是放在我用以下聲明光標的兩種服務器的負載。

宣言1: DECLARE DB_CURSOR_01 CURSOR本地靜態READ_ONLY FORWARD_ONLY FOR

宣言2: DECLARE DB_CURSOR_02 CURSOR FAST_FORWARD FOR

注:我不使用鼠標的默認聲明,我正在使用其他類型的遊標使其工作得更快,據我所知,上面提到的聲明1比聲明2更快,糾正我,如果我錯了。

問: 由行操作做行的另一種方式是通過「在使用臨時表圈」。所以,現在我的問題是,如果我使用臨時表將所有遊標轉換爲while循環,是否有助於提高服務器性能?

其實我們的DBA指出,服務器的性能是因爲遊標的影響,如果我把那麼多的努力,所有這些光標到while循環,它會給我帶來的性能優勢的轉換?或者我在上面聲明的聲明1中聲明遊標的方式與while循環的性能相同?

+0

帶臨時表的while循環是怎麼樣的? – IngoB

+0

您確定無法用單個更新替代遊標(例如,在臨時表中)嗎?我們過去用遊標開發了大量的遷移,一次遷移需要數小時才能運行。然後我們意識到,用簡單的更新來替換所有的遊標是非常容易的,這使得與光標解決方案相比,遷移閃電很快。 – IngoB

+0

@IngoB在我的情況下,我不只是在單個表上進行更新,在我的遊標下,我正在執行的操作可能與執行其他選擇語句的計算然後將數據插入到其他表中一樣。這只是一個例子,我可能會有不同的遊標執行不同的操作。 –

回答

0

遊標在SQL Server中是非常慢的。在其他RDBMS上,例如Sybase,它們都可以。

下面是如何處理與他們實際的做法:

在我的「優化」狡猾的老代碼的經驗,使用遊標的主要問題是,當它們是基於一個複雜的查詢。通過複雜的查詢,我的意思是一個具有多個連接和/或複雜連接條件的查詢。 光標確實是什麼,每次迭代,它具有運行此聯接操作,這可能需要比循環的體內運作更多的時間。

在類似這些情況下,方式更有效地運行單個選擇到一個臨時表,然後使用臨時表中的光標,一個替代的方式是使用STATICINSENSITIVE關鍵字(MSDN)。要考慮的一個重要方面是併發性;通過將主遊標查詢的結果保存到臨時表中,可以防止對遊標可見的基礎表的更改。

第二方面要考慮的是一個光標內選擇查詢。這是非常重要的,因爲每個查詢都針對每個遊標迭代運行,因此在大型表上進行選擇會消耗大量資源。

我看到其中一些尤其是「不可靠」的代碼:

  • 甲查詢表以返回使用光標的取變量作爲濾波器的一個單一值。 - 這個表應該是JOIN ed的主遊標查詢。通過這種方式,這個表格只被查詢一次,並將結果保存到臨時表格中。
  • 查詢表以根據某些條件返回一些數據,然後再次查詢以基於相同條件返回更多數據(不同列)。 - 這兩個選擇應該合併爲一個,以便所有數據(所有列)可以一次返回。

如果你有嵌套遊標(一個在另一個內),它是殺手。嘗試刪除嵌套。

如果你有很多使用遊標的地方,優先考慮與上述情況相匹配的地方。

P.S.雖然循環是自己的不會救你。您仍然需要使用臨時表並在臨時表上有適當的索引。請參閱:https://dba.stackexchange.com/questions/84365/why-choose-a-top-query-and-temporary-table-instead-of-a-cursor-for-a-loop

上述鏈接到Aaron Bertrand博客,其中討論性能以及遊標選項的建議。