2009-08-19 37 views
24

所以,最近一個DBA是想告訴我們,我們不能使用的SQL Server的SELECT INTO和阻止隨着臨時表

SELECT X, Y, Z 
INTO #MyTable 
FROM YourTable 

的語法來創建我們的環境中臨時表,因爲這句法會導致鎖定在存儲過程執行期間在TempDB上執行。現在,我已經發現了許多詳細說明臨時表的工作方式,執行範圍,清理等等的內容。但是對於我的生活,我沒有看到任何關於阻塞因爲它們的使用。

我們試圖找到證據證明我們不應該通過併爲所有臨時表執行CREATE TABLE #MyTable ...,但雙方都無法找到證據。我正在尋找人們擁有的任何見解。

其他信息

目前與SQL Server 2005的工作,並很快被SQL Server 2008的(企業版)

+0

你爲什麼不考呢? – automatic 2009-08-19 21:24:26

+0

我們一直沒有看到任何屏蔽..... 我們正試圖找到某種形式的證據,或更好的文檔 – 2009-08-19 21:41:15

回答

34

該建議已被左右浮動for a long time

瓶頸在SQL Server 6.5

很多人使用SELECT ... INTO查詢 創建一個臨時表,一些 這樣的:

SELECT * INTO #TempTable FROM sourceTable會

雖然該W獸人,它創建鎖 對SELECT語句 的 期間tempdb數據庫(相當長一段時間,如果你有拖網 通過源 表中的大量數據,以及更長的猶若 SELECT ... INTO位於 長時間運行的顯式事務處理的開始處) 鎖定就位時,沒有其他 用戶可以創建臨時表。 瓶頸的實際位置是對tempdb系統表的一個 鎖定。在稍後的 版本的SQL Server中,鎖定 模型已更改,並且問題是 可以避免。

幸運的是,這只是SQL 6.5的一個問題。它在7.0和更高版本中被修復。

+3

+1我認爲dba的建議然後屬於神話的範疇 – 2009-08-19 21:49:13

+0

+1鏈接到一個恆星的解決方法 - WHERE 1 = 0 – SqlRyan 2009-08-23 15:27:52

+0

您可以請更新您的答案與SQL的新功能,因爲您的答案首先在谷歌搜索,它應該是有效的最新版本。 TIA :) – 2014-08-26 14:29:32

0

我會說缺乏鎖定證據意味着沒有鎖定,這是你的證明。爲什麼在臨時表中創建的方法(CREATE或SELECT ... INTO)在鎖定TempDB方面有所作爲?

+0

這就是我們的想法和論點......但他們是堅持使用SELECT INTO會在存儲過程期間導致阻塞。 – 2009-08-19 21:41:57

+0

我想知道爲什麼臨時表被鎖定也是一個問題。如果它是一個全球臨時表,那是一個不同的故事。 – 2009-08-19 21:42:53

+0

@rexem:OP的DBA並不是說臨時表已被鎖定,但TempDB,所有臨時表的位置以及其他臨時存儲都被鎖定。不知道DBA是否正確,我會推遲到聰明的人。 – 2009-08-20 03:51:13

0

那麼如果這是真的,那麼mssql會有問題,因爲任何大型查詢都可以使用tempdb來保存行的副本。這通常可以在查詢計劃中作爲表假脫機工具看到,或者如果HASH JOIN運算符在其存儲區的內存不足時可以使用它。

你可以看看使用表變量,mssql將嘗試在內存中存儲它們,並在它們變大時移動到tempdb。

DECLARE @foo TABLE (x int, y int, z int) 
INSERT INTO @foo(x, y, z) SELECT x, y, z FROM YourTable 

當然,你應該評估是否需要首先臨時表和副本。儘管如果查詢足夠複雜以至於使用臨時表的可讀性要高得多,那麼對於臨時表而言,值也可能足夠複雜。

16

這可能會浮現很長一段時間,餵養各種'顧問'的口袋。像所有的神話一樣,它具有真理和許多BS的核心。

事實:SQL 2000和以前的版本已經知道有關tempdb中擴展區分配的爭用問題。實際上,所有數據庫中的爭用都是真實的,但由於tempdb使用量過大,在tempdb中更加明顯。據記載在KB328551

當tempdb數據庫是大量使用時,SQL Server可能會遇到 競爭,當它試圖分配 頁 。

從sysprocesses系統表 輸出,waitresource該可能顯示 爲 「2:1:1」(PFS頁)或 「2:1:3」(SGAM 頁)。根據 爭用的程度,這也可能導致SQL 服務器短時間內顯示爲無響應的 。

這些操作大量使用tempdb:
重複創建和臨時 表降(本地或全局)。
使用tempdb存儲 目的的表變量。
與 CURSORS相關的工作表。
與 關聯的工作表是一個ORDER BY子句。
與GROUP BY子句關聯的工作表。
與HASH計劃相關的工作文件。

重度和重要的使用這些 活動可能導致 的爭用問題。

跟蹤標誌-T1118在SQL Server 2000 SP3這是強迫SQL使用混合頁分配一個循環算法加入。這種新算法與將tempdb部署在一組相同大小的文件之上的做法相關聯,每個CPU對應一個,這樣可以緩解爭用。跟蹤標誌在SQL 2005/2008中仍然存在,儘管它不太可能需要。

關於這個神話的一切都非常BS。

  • 確實使用#temp表格會導致阻塞?不,在最壞的情況下,增加了SQL 2000及更早版本中負載下的爭用,但與說它阻塞任何東西相去甚遠。您必須首先進行測量,並看到情況如何,如果是這樣,則部署修復措施(爲每個CPU分配一個tempdb文件,使其等於大小,打開-T1118)。
  • 將select ... into #temp在選擇期間阻塞某些東西?不是真的。
  • 是否將select ... ...變成#temp塊,用於包含select的存儲過程的持續時間?一定不行。只是閱讀這一說法,我就笑了起來。

欲瞭解更多詳情,還有這篇文章:Misconceptions around TF1118

+0

感謝您的信息! – 2009-08-20 13:59:33

+1

如果[select ... into #temp]處於事務中,在事務提交之前[select * from sysobjects]將在其他任何會話中被阻止。 – 2015-08-19 06:49:44

0

SELECT INTO #temp_table在聲明的持續時間內在tempdb中保存shema鎖,因爲它正在完成的部分工作是創建表。這與首先​​使用CREATE TABLE #....創建表格然後運行基於集合的INSERT完全不同。 SELECT INTO確實比INSERT具有更多的優勢,特別是如果數據庫的恢復模型是簡單日誌或擴展日誌,那麼操作的記錄會被最小化。

10

爲什麼不做以下幾點?

SELECT X, Y, Z 
INTO #MyTable 
FROM YourTable 
WHERE 1 = 2 

聲明會立即運行 - 創建臨時表,並避免任何可能的鎖定。然後你可以像往常一樣插入它:

INSERT #MyTable 
SELECT X, Y, Z 
FROM YourTable 
+1

針對利用系統漏洞的黑客+1。 – jp2code 2012-07-19 20:00:38

1

如果您在事務中創建#temp表,您可以獲得阻塞。雖然這通常不被推薦,但我已經看到這樣做了很多。

但是,由tempdb中的某些系統表導致的阻塞不會影響創建臨時表的其他連接(可能除了2000版之前的SQL版本以外)。這意味着在tempdb上運行sp_spacesused將被阻塞,除非您將事務隔離級別設置爲未提交讀取。同時從SSMS查看tempdb上的屬性將失敗並超時,因爲它正在使用讀提交事務隔離級別。