TempDB--臨時表的緩存


--==========================================================================

在博客園看到一篇文章《SQLServer Temp tables 數據疑問》,文章中問道在沒有任何負載情況下,還有大量的臨時表,這是為什么?

--==========================================================================

讓我們來實驗探索下

首先選擇任何一個用戶數據庫,執行以下腳本:

CREATE PROCEDURE USP_TempTableTest
AS
BEGIN
    SET NOCOUNT ON;

    CREATE TABLE #TB1(C11 INT,C22 INT)
    INSERT INTO #TB1
    SELECT 1,1

    SELECT * FROM #TB1
END
GO

EXEC USP_TempTableTest

按照通用的理解,存儲過程中的臨時表會在調用中創建,在存儲過程調用結束后釋放,存儲過程執行結束后,我們不應該在tempdb中找到#TB1開頭的臨時表。

讓我們來檢查下

use tempdb
go
--======================================
--查看臨時表的列
SELECT OBJECT_NAME(OBJECT_ID) AS ObjName,
* FROM SYS.all_columns
WHERE OBJECT_NAME(OBJECT_ID) LIKE '%#%'

運行以上代碼,可以很容易找到:

列名C11和C22和我們存儲過程中定於的臨時表列名一樣,只是換了個馬甲而已,別告訴我換了馬甲你們就不認識”它“咯

--================================================================

解釋:

上面看到的#A2206DOC這個臨時表並不是我們存儲過程中使用到的#TB1,但是但是兩者存在一定關聯。想象一下,每次存儲過程執行,都需要創建和釋放臨時表,而創建和釋放臨時表又涉及到修改很多系統表的數據,而如果緩存這個臨時表,那么下一次調用存儲過程時,就避免創建和釋放臨時表所照成的資源消耗,從而達到一定的性能提升。

 專業解釋:

SQL Server刪除一個臨時對象時,不移除該對象的條目,當再次使用時,就無須重新創建臨時對象,SQL Server為臨時對象緩存一個數據頁和一個IAM頁,並回收剩余頁,如果臨時表的大小超過8MB,回收會異步進行。

--==================================================================

問題1: 多個存儲過程並發調用的時候怎么辦?

當並發調用時,會生成多個類似的臨時表”緩存“以供調用,並保證一個臨時表”緩存“在一個時間點內只能被一個回話執行的存儲過程訪問到,在訪問結束后,會清理該臨時表”緩存“的數據,然后供下一個回話使用。

 

問題2: 什么樣的臨時表會被”緩存“

當然不是所有臨時表都會被緩存,需要滿足一定的條件:

1. 沒有創建命名約束

2. 臨時對象在創建后沒有執行影響臨時表的數據定義語言DDL操作(如創建索引和創建統計)

3. 沒有使用動態SQL創建臨時對象

4. 臨時對象被創建在另一個對象的內部,如存儲過程、觸發器、用戶自定義函數或臨時對象是一個用戶自定義表值函數的分會表

 --=====================================================================

 依舊妹子引狼(最近小忙,不能保證妹子質量,勿怪)

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM