表變量和臨時表

 表變量存儲在內存中,而臨時表存儲在tempdb中,會涉及到物理IO讀寫,那麼咱們是否能夠由此得出結論,使用表變量要比使用臨時表效率高呢?相信有一部分人會和我有一樣的想法,使用表變量的效率高,真是如此嗎?先從一次優化存儲過程的經歷提及。sql

      存儲過程涉及到兩個表,一個是用戶今日積分表@tableUserScore(數據源來自用戶積分詳情表中的今日數據),一個是用戶積分統計表UserScoreSum,該存儲過程邏輯就是統計@tableUserScore中用戶不一樣緣由的積分值,生成到表UserScoreSum中。數據量不算很大,@tableUserScore中大概40萬條,但這個存儲過程執行時間卻有些驚人,一般都在1個小時之上。優化的最終結果是將表變量@tabeUserScore換成了臨時表#tableUserScore,並在userid和reason上添加了聯合索引,優化的效果是執行時間控制在了40S左右。臨時表和表變量效率相差百倍,此次優化經歷讓我對臨時表和表變量有了從新認識,也有了一連串的疑問,它們是如何存儲的,效率如何,如何選用?數據庫

declare @tableUserScore table(
    userid int, --用戶編號
    name varchar(10), --用戶姓名
    reason varchar(32), --積分緣由
    score int --積分值
)

create table UserScoreSum(
    userid int, --用戶編號
    name varchar(10), --用戶姓名
    createTime datetime, --時間
    reason1Score int, --緣由1積分值
    reason2Score int, --緣由2積分值
    reason3Score int, --緣由3積分值
    reason4Score int, --緣由4積分值
)

   如下是我的翻閱資料後的理解,總結出來但願能給和我有一樣認識的人提個醒,起到拋磚引玉的做用,也但願你們對理解錯誤之處提出指正。性能

     臨時表大數據

     臨時表有兩種類型:本地表和全局表。在與首次建立或引用表時相同的 SQL Server 實例鏈接期間,本地臨時表只對於建立者是可見的。當用戶與 SQL Server 實例斷開鏈接後,將刪除本地臨時表。全局臨時表在建立後對任何用戶和任何鏈接都是可見的,當引用該表的全部用戶都與 SQL Server 實例斷開鏈接後,將刪除全局臨時表。本地臨時表的名稱都是以「#」爲前綴,全局臨時表的名稱都是以「##」爲前綴。優化

     臨時表存儲在tempdb中,所以臨時表的訪問是有可能形成物理IO的,固然在修改時也須要生成日誌來確保一致性,同時鎖機制也是不可缺乏的。spa

     臨時表能夠建立索引,也能夠定義統計數據,因此能夠用數據定義語言(DDL)的聲明來阻止臨時表添加的限制,約束,並參照完整性,如主鍵和外鍵約束。日誌

     表變量code

     表變量是變量的一種,表變量也分爲本地及全局的兩種,本地表變量的名稱都是以「@」爲前綴,只有在本地當前的用戶鏈接中才能夠訪問。全局的表變量的名稱都是以「@@」爲前綴,通常都是系統的全局變量,像咱們經常使用到的,如@@Error表明錯誤的號,@@RowCount表明影響的行數。orm

     表變量存放在內存中,正是由於這一點全部用戶訪問表變量的時候SQL Server是不須要生成日誌。同時變量是不須要考慮其餘會話訪問的問題,所以也不須要鎖機制,對於很是繁忙的系統來講,避免鎖的使用能夠減小一部分系統負載。[表變量存放在內存是有必定限制的,若是表變量數據量超過閾值,會把內存耗盡,而後使用TempDB的空間,這樣主要仍是使用硬盤空間,但同時把內存基本耗盡,增長了內存調入調出的機會,反而下降速度]索引

     表變量另外還有一個限制就是不能建立索引,固然也不存在統計數據的問題,所以在用戶訪問表變量的時候也就不存在執行計劃選擇的問題了(也就是覺得着編譯階段後就沒有優化階段了),這一特性有的時候是件好事,而有些時候卻會形成一些麻煩。

     臨時表 vs. 表變量

     1.存儲位置:臨時表是利用了硬盤(tempdb數據庫) ,表名變量是佔用內存,所以小數據量固然是內存中的表變量更快。當大數據量時,就不能用表變量了,太耗內存了。大數據量時適合用臨時表。

     2.性能:不能一律而論,表變量存儲數據有個性能臨界點,在這個臨界點以內,表變量比臨時錶快,表變量是存儲在內存中的。

     3.索引:表變量不支持索引和統計數據,但能夠有主鍵;臨時表則能夠支持索引和統計數據。

     咱們對於較小的臨時計算用數據集考慮使用表變量。若是數據集比較大,若是在代碼中用於臨時計算,同時這種臨時使用永遠都是簡單的全數據集掃描而不須要考慮什麼優化,好比說沒有分組或分組不多的聚合(好比說COUNT、SUM、AVERAGE、MAX等),也能夠考慮使用表變量。使用表變量另一個考慮因素是應用環境的內存壓力,若是代碼的運行實例不少,就要特別注意內存變量對內存的消耗。通常對於大的數據集咱們最好使用臨時表,同時建立索引。

相關文章
相關標籤/搜索