sql server 存储过程中使用变量表,临时表的分析(续)
?最近,我有一朋友,對我說他的數據庫中的很多存儲過程,執行都是超時.讓我替他看看是什么原因.我一看,原來他的存儲過程中用了很多的臨時表與變量表.于是我跟他說過猶不及.
在存儲過程中使用臨時表或變量表,使用的好可以提高速度,使用的不好,可能會起到反作用. 然后給了他幾個示例讓他自己去看,然后針對自己的數據庫進行修改.
那么表變量一定是在內存中的嗎?不一定.
通常情況下,表變量中的數據比較少的時候,表變量是存在于內存中的。但當表變量保留的數據較多時,內存中容納不下,那么它必須在磁盤上有一個位置來存儲數據。與臨時表類似,表變量是在?tempdb?數據庫中創建的。如果有足夠的內存,則表變量和臨時表都在內存(數據緩存)中創建和處理。
?說明:
???? 1) CPU-- 事件(sql語句)使用的 CPU 時間(毫秒)。
? ?? 2)? Reads--由服務器代表事件讀取邏輯磁盤的次數。這些讀取操作數包含在語句執行期間讀取表和緩沖區的次數。
? ?? 3) Writes--由服務器代表事件寫入物理磁盤的次數。
示例1.變量表
1) 10000條記錄?
declare @t table
(
id nvarchar(50),
supno nvarchar(50),
eta datetime
)
insert? @t
select top 10000 ID,supno,eta from 表
--cpu :125?? ?reads :13868??? writes: 147?
--表 '#286302EC'。掃描計數 0,邏輯讀取 10129 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。
--表 '表'。掃描計數 1,邏輯讀取 955 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。
declare @t table
(
id nvarchar(50),
supno nvarchar(50),
eta datetime
)
insert? @t
select top 1000 ID,supno,eta from 表
--?? ?cpu:46?? ?reads:2101???? writes:?? ?17????
--表 '#44FF419A'。掃描計數 0,邏輯讀取 1012 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。
--表 '表'。掃描計數 1,邏輯讀取 108 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。
--示例2。臨時表:
create table #t
(
id nvarchar(50),
supno nvarchar(50),
eta datetime
)
end
insert #t
select top 10000 ID,supno,eta
from 表
--cpu :125?? ?reads:13883?????? writes:148?? ?
--表 '#t00000000005'。掃描計數 0,邏輯讀取 10129 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。
--表 '表'。掃描計數 1,邏輯讀取 955 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。
create table #t
(
id nvarchar(50),
supno nvarchar(50),
eta datetime
)
insert #t
select top 1000 ID,supno,eta
from 表
--cpu: 62?? ?reads: 2095?? ???? writes: 17
--表 '#t00000000003'。掃描計數 0,邏輯讀取 1012 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。
--表 '表'。掃描計數 1,邏輯讀取 108 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。
--示例3。不創建臨時表,直接插入到臨時表
select top 10000 ID,supno,eta
into #t
from 表
--cpu:31?? ?reads:1947?? ???? writes:83
--表 '表'。掃描計數 1,邏輯讀取 955 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。
select top 1000 ID,supno,eta
into #t
from 表
--cpu: 0?? ?reads: 997?? ???? writes:11
--表 '表'。掃描計數 1,邏輯讀取 108 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。
從以上的分析中可以看出,如果使用3)方式,則會少建一個臨時表.那么IO中的讀寫也將減少次數.
1)與2)都會有先建臨時表的動作,并進行相應的IO讀取操作.?
從sql語句對服務器的cpu使用上來看,第三種情況cpu使用率也相對較低.?
從物理寫入磁盤操作來看,第三種情況的物理寫入次數較少.
在什么情況下使用表變量來代替臨時表:
取決于以下三個因素:
| ? | 插入到表中的行數。本人認為最好是小于1000行,具體情況具體分析. |
| ? | 從中保存查詢的重新編譯的次數。 |
| ? | 查詢類型及其對性能的指數和統計信息的依賴性。 |
在某些情況下,可將一個具有臨時表的存儲過程拆分為多個較小的存儲過程,以便在較小的單元上進行重新編譯。?
個人建議,當記錄行小于1000行的情況下,應盡量使用表變量,除非數據量非常大(大于1000行)并且需要重復使用表。在這種情況下,可以在臨時表上創建索引以提高查詢性能。但是,各種方案可能互不相同。
Microsoft 建議您做一個測試,來驗證表變量對于特定的查詢或存儲過程是否比臨時表更有效。
總結
以上是生活随笔為你收集整理的sql server 存储过程中使用变量表,临时表的分析(续)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 市面上很多瓷砖品牌,雁京陶瓷有什么优势?
- 下一篇: 多层住宅小区家里的窗户外面抹灰层属于公共