主頁(yè) > 知識(shí)庫(kù) > SQLSERVER收集語(yǔ)句運(yùn)行的統(tǒng)計(jì)信息并進(jìn)行分析

SQLSERVER收集語(yǔ)句運(yùn)行的統(tǒng)計(jì)信息并進(jìn)行分析

熱門標(biāo)簽:承德地圖標(biāo)注公司名需要花錢嗎 北京400電話辦理多少錢 美團(tuán)地圖標(biāo)注商戶認(rèn)證注冊(cè) 浙江穩(wěn)定外呼系統(tǒng)供應(yīng)商 榕城市地圖標(biāo)注 電銷外呼系統(tǒng)軟件功能 咸陽(yáng)電腦外呼系統(tǒng)運(yùn)營(yíng)商 慶陽(yáng)地圖標(biāo)注 怎么給高德做地圖標(biāo)注
對(duì)于語(yǔ)句的運(yùn)行,除了執(zhí)行計(jì)劃本身,還有一些其他因素要考慮,例如語(yǔ)句的編譯時(shí)間、執(zhí)行時(shí)間、做了多少次磁盤讀等。

如果DBA能夠把問(wèn)題語(yǔ)句單獨(dú)測(cè)試運(yùn)行,可以在運(yùn)行前打開下面這三個(gè)開關(guān),收集語(yǔ)句運(yùn)行的統(tǒng)計(jì)信息。
這些信息對(duì)分析問(wèn)題很有價(jià)值。
復(fù)制代碼 代碼如下:

SET STATISTICS TIME ON
SET STATISTICS IO ON
SET STATISTICS PROFILE ON

SET STATISTICS TIME ON
--------------------------------------------------------------------------------
請(qǐng)先來(lái)看看SET STATISTICS TIME ON會(huì)返回什么信息。先運(yùn)行語(yǔ)句:
復(fù)制代碼 代碼如下:

DBCC DROPCLEANBUFFERS
--清除buffer pool里的所有緩存數(shù)據(jù)
DBCC freeproccache
GO
--清除buffer pool里的所有緩存的執(zhí)行計(jì)劃
SET STATISTICS TIME ON
GO
USE [AdventureWorks]
GO
SELECT DISTINCT([ProductID]),[UnitPrice] FROM [dbo].[SalesOrderDetail_test]
WHERE [ProductID]=777
GO
SET STATISTICS TIME OFF
GO

除了結(jié)果集之外,SQLSERVER還會(huì)返回下面這兩段信息
復(fù)制代碼 代碼如下:

SQL Server 分析和編譯時(shí)間:
CPU 時(shí)間 = 15 毫秒,占用時(shí)間 = 104 毫秒。
SQL Server 分析和編譯時(shí)間:
CPU 時(shí)間 = 0 毫秒,占用時(shí)間 = 0 毫秒。
(4 行受影響)
SQL Server 執(zhí)行時(shí)間:
CPU 時(shí)間 = 171 毫秒,占用時(shí)間 = 1903 毫秒。
SQL Server 分析和編譯時(shí)間:
CPU 時(shí)間 = 0 毫秒,占用時(shí)間 = 0 毫秒。

大家知道SQLSERVER執(zhí)行語(yǔ)句是分以下階段:分析-》編譯-》執(zhí)行
根據(jù)表格的統(tǒng)計(jì)信息分析出比較合適的執(zhí)行計(jì)劃,然后編譯語(yǔ)句,最后執(zhí)行語(yǔ)句

下面說(shuō)一下上面的輸出是什么意思
--------------------------------------------------------------------------------
1、CPU時(shí)間 :這個(gè)值的含義指的是在這一步,SQLSERVER所花的純CPU時(shí)間是多少。也就是說(shuō),語(yǔ)句花了多少CPU資源
2、占用時(shí)間 :此值指這一步一共用了多少時(shí)間。也就是說(shuō),這是語(yǔ)句運(yùn)行的時(shí)間長(zhǎng)短,有些動(dòng)作會(huì)發(fā)生I/O操作,產(chǎn)生了I/O等待,或者是遇到阻塞、產(chǎn)生了阻塞等待。總之時(shí)間用掉了,但是沒有用CPU資源。所以占用時(shí)間比CPU時(shí)間長(zhǎng)是很正常的 ,但是CPU時(shí)間是語(yǔ)句在所有CPU上的時(shí)間總和。如果語(yǔ)句使用了多顆CPU,而其他等待幾乎沒有,那么CPU時(shí)間大于占用時(shí)間也是正常的
3、分析和編譯時(shí)間:這一步,就是語(yǔ)句的編譯時(shí)間。由于語(yǔ)句運(yùn)行之前清空了所有執(zhí)行計(jì)劃,SQLSERVER必須要對(duì)他編譯。
這里的編譯時(shí)間就不為0了。由于編譯主要是CPU的運(yùn)算,所以一般CPU時(shí)間和占用時(shí)間是差不多的。如果這里相差比較大,就有必要看看SQLSERVER在系統(tǒng)資源上有沒有瓶頸了。
這里他們是一個(gè)15毫秒,一個(gè)是104毫秒
4、SQLSERVER執(zhí)行時(shí)間: 語(yǔ)句真正運(yùn)行的時(shí)間。由于語(yǔ)句是第一次運(yùn)行,SQLSERVER需要把數(shù)據(jù)從磁盤讀到內(nèi)存里,這里語(yǔ)句的運(yùn)行發(fā)生了比較長(zhǎng)的I/O等待。所以這里的CPU時(shí)間和占用時(shí)間差別就很大了,一個(gè)是171毫秒,而另一個(gè)是1903毫秒

總的來(lái)講,這條語(yǔ)句花了104+1903+186=2193毫秒,其中CPU時(shí)間為15+171=186毫秒。語(yǔ)句的主要時(shí)間應(yīng)該是都花在了I/O等待上

現(xiàn)在再做一遍語(yǔ)句,但是不清除任何緩存
復(fù)制代碼 代碼如下:

SET STATISTICS TIME ON
GO
SELECT DISTINCT([ProductID]),[UnitPrice] FROM [dbo].[SalesOrderDetail_test]
WHERE [ProductID]=777
GO
SET STATISTICS TIME OFF
GO

這次比上次快很多。輸出時(shí)間統(tǒng)計(jì)信息是:
復(fù)制代碼 代碼如下:

SQL Server 分析和編譯時(shí)間:
CPU 時(shí)間 = 0 毫秒,占用時(shí)間 = 0 毫秒。
SQL Server 分析和編譯時(shí)間:
CPU 時(shí)間 = 0 毫秒,占用時(shí)間 = 0 毫秒。
(4 行受影響)
SQL Server 執(zhí)行時(shí)間:
CPU 時(shí)間 = 156 毫秒,占用時(shí)間 = 169 毫秒。
SQL Server 分析和編譯時(shí)間:
CPU 時(shí)間 = 0 毫秒,占用時(shí)間 = 0 毫秒。

由于執(zhí)行計(jì)劃被重用,“SQL分析和編譯時(shí)間” CPU時(shí)間是0,占用時(shí)間是0
由于數(shù)據(jù)已經(jīng)緩存在內(nèi)存里,不需要從磁盤上讀取,SQL執(zhí)行時(shí)間 CPU時(shí)間是156,占用時(shí)間這次和CPU時(shí)間非常接近,是169。

這里省下運(yùn)行時(shí)間1903-169=1734毫秒,從這里可以再次看出,緩存對(duì)語(yǔ)句執(zhí)行性能起著至關(guān)重要的作用
為了不影響其他測(cè)試,請(qǐng)運(yùn)行下面的語(yǔ)句關(guān)閉SET STATISTICS TIME ON
復(fù)制代碼 代碼如下:

SET STATISTICS TIME OFF 
GO

SET STATISTICS IO ON
--------------------------------------------------------------------------------
這個(gè)開關(guān)能夠輸出語(yǔ)句做的物理讀和邏輯讀的數(shù)目。對(duì)分析語(yǔ)句的復(fù)雜度有很重要的作用
還是以剛才那個(gè)查詢作為例子
復(fù)制代碼 代碼如下:

DBCC DROPCLEANBUFFERS
GO
SET STATISTICS IO ON
GO
SELECT DISTINCT([ProductID]),[UnitPrice] FROM [dbo].[SalesOrderDetail_test]
WHERE [ProductID]=777
GO

他的返回是: 
(4 行受影響)
表 'SalesOrderDetail_test'。掃描計(jì)數(shù) 5,邏輯讀取 15064 次,物理讀取 0 次,預(yù)讀 15064 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預(yù)讀 0 次。
各個(gè)輸出的含義是:
--------------------------------------------------------------------------------
表:表的名稱。這里的表就是SalesOrderDetail_test

掃描計(jì)數(shù):執(zhí)行的掃描次數(shù)。按照?qǐng)?zhí)行計(jì)劃,表格被掃描了幾次。一般來(lái)講大表掃描的次數(shù)越多越不好。唯一的例外是如果執(zhí)行計(jì)劃選擇了并發(fā)運(yùn)行, 由多個(gè)thread線程同時(shí)做一個(gè)表的讀取,每個(gè)thread讀其中的一部分,但是這里會(huì)顯示所有thread的數(shù)目。也就是有幾個(gè)thread在并發(fā)做, 就會(huì)有幾個(gè)掃描。這時(shí)數(shù)目大一點(diǎn)沒問(wèn)題的。

邏輯讀?。簭臄?shù)據(jù)緩存讀取的頁(yè)數(shù)。頁(yè)數(shù)越多,說(shuō)明查詢要訪問(wèn)的數(shù)據(jù)量就越大,內(nèi)存消耗量越大,查詢也就越昂貴。

可以檢查是否應(yīng)該調(diào)整索引,減少掃描的次數(shù),縮小掃描范圍
物理讀?。簭拇疟P讀取的頁(yè)數(shù)
預(yù)讀:為進(jìn)行查詢而預(yù)讀入緩存的頁(yè)數(shù)
物理讀取+預(yù)讀:就是SQLSERVER為了完成這句查詢而從磁盤上讀取的頁(yè)數(shù)。如果不為0,說(shuō)明數(shù)據(jù)沒有緩存在內(nèi)存里。運(yùn)行速度一定會(huì)受到影響
LOB邏輯讀?。簭臄?shù)據(jù)緩存讀取的text、ntext、image、大值類型(varchar(max)、nvarchar(max)、varbinary(max))頁(yè)的數(shù)目
LOB物理讀?。簭拇疟P讀取的text、ntext、image、大值類型頁(yè)的數(shù)目
LOB預(yù)讀:為進(jìn)行查詢而放入緩存的text、ntext、image、大值類型頁(yè)的數(shù)目
然后再來(lái)運(yùn)行一遍,不清空緩存
復(fù)制代碼 代碼如下:

SET STATISTICS IO ON
GO
SELECT DISTINCT([ProductID]),[UnitPrice] FROM [dbo].[SalesOrderDetail_test]
WHERE [ProductID]=777
GO

結(jié)果集返回:
復(fù)制代碼 代碼如下:

1 表 'SalesOrderDetail_test'。掃描計(jì)數(shù) 5,邏輯讀取 15064 次,物理讀取 0 次,預(yù)讀 0 次,lob 邏輯讀取 0 次,
2 lob 物理讀取 0 次,lob 預(yù)讀 0 次。

這次邏輯讀取不變,還是15064頁(yè)。但是物理讀取和預(yù)讀都是0了。說(shuō)明數(shù)據(jù)已經(jīng)緩存在內(nèi)存里第二次運(yùn)行不需要再?gòu)拇疟P上讀一遍,節(jié)省了時(shí)間為了不影響其他測(cè)試,請(qǐng)運(yùn)行下面語(yǔ)句關(guān)閉SET STATISTICS IO ON
復(fù)制代碼 代碼如下:

SET STATISTICS IO OFF
GO

SET STATISTICS PROFILE ON
--------------------------------------------------------------------------------
這是三個(gè)設(shè)置中返回最復(fù)雜的一個(gè),他返回語(yǔ)句的執(zhí)行計(jì)劃,以及語(yǔ)句運(yùn)行在每一步的實(shí)際返回行數(shù)統(tǒng)計(jì)。
通過(guò)這個(gè)結(jié)果,不僅可以得到執(zhí)行計(jì)劃,理解語(yǔ)句執(zhí)行過(guò)程,分析語(yǔ)句調(diào)優(yōu)方向,也可以判斷SQLSERVER是否
選擇了一個(gè)正確的執(zhí)行計(jì)劃。
復(fù)制代碼 代碼如下:

SET STATISTICS PROFILE ON
GO
SELECT COUNT(b.[SalesOrderID])
FROM [dbo].[SalesOrderHeader_test] a
INNER JOIN [dbo].[SalesOrderDetail_test] b
ON a.[SalesOrderID]=b.[SalesOrderID]
WHERE a.[SalesOrderID]>43659 AND a.[SalesOrderID]53660
GO

返回的結(jié)果集很長(zhǎng),下面說(shuō)一下重要字段
--------------------------------------------------------------------------------

注意:這里是從最下面開始向上看的,也就是說(shuō)從最下面開始一直執(zhí)行直到得到結(jié)果集所以(行1)里的rows字段顯示的值就是這個(gè)查詢返回的結(jié)果集。

而且有多少行表明SQLSERVER執(zhí)行了多少個(gè)步驟,這里有6行,表明SQLSRVER執(zhí)行了6個(gè)步驟!!
Rows:執(zhí)行計(jì)劃的每一步返回的實(shí)際行數(shù)
Executes:執(zhí)行計(jì)劃的每一步被運(yùn)行了多少次
StmtText:執(zhí)行計(jì)劃的具體內(nèi)容。執(zhí)行計(jì)劃以一棵樹的形式顯示。每一行都是運(yùn)行的一步,都會(huì)有結(jié)果集返回,也都會(huì)有自己的cost
EstimateRows:SQLSERVER根據(jù)表格上的統(tǒng)計(jì)信息,預(yù)估的每一步的返回行數(shù)。在分析執(zhí)行計(jì)劃時(shí),我們會(huì)經(jīng)常將Rows和EstimateRows這兩列做對(duì)比,先確認(rèn)SQLSERVER預(yù)估得是否正確,以判斷統(tǒng)計(jì)信息是否有更新
EstimateIO:SQLSERVER根據(jù)EstimateRows和統(tǒng)計(jì)信息里記錄的字段長(zhǎng)度,預(yù)估的每一步會(huì)產(chǎn)生的I/O cost
EstimateCPU:SQLSERVR根據(jù)EstimateRows和統(tǒng)計(jì)信息里記錄的字段長(zhǎng)度,以及要做的事情的復(fù)雜度,預(yù)估每一步會(huì)產(chǎn)生的CPU cost
TotalSubtreeCost:SQLSERVER根據(jù)EstimateIO和EstimateCPU通過(guò)某種計(jì)算公式,計(jì)算出每一步執(zhí)行計(jì)劃子樹的cost (包括這一步自己的cost和他的所有下層步驟的cost總和),下面介紹的cost說(shuō)的都是這個(gè)字段值
Warnings:SQLSERVER在運(yùn)行每一步時(shí)遇到的警告,例如,某一步?jīng)]有統(tǒng)計(jì)信息支持cost預(yù)估等。
Parallel:執(zhí)行計(jì)劃的這一步是不是使用了并行的執(zhí)行計(jì)劃

從上面結(jié)果可以看出執(zhí)行計(jì)劃分成4步,其中第一步又分成并列的兩個(gè)子步驟

步驟a1(第5行):從[SalesOrderHeader_test]表里找出所有a.[SalesOrderID]>43659 AND a.[SalesOrderID]53660的值
因?yàn)楸碓谶@個(gè)字段上有一個(gè)聚集索引,所以SQL可以直接使用這個(gè)索引的seek
SQL預(yù)測(cè)返回10000條記錄,實(shí)際也就返回了10000條記錄.。這個(gè)預(yù)測(cè)是準(zhǔn)確的。這一步的cost是0.202(totalsubtreecost)
步驟a2(第6行):從[SalesOrderDetail_test]表里找出所有 a.[SalesOrderID]>43659 AND a.[SalesOrderID]53660的值
因?yàn)楸碓谶@個(gè)字段上有一個(gè)非聚集索引,所以SQL可以直接使用這個(gè)索引的seek 這里能夠看出SQL聰明的地方。雖然查詢語(yǔ)句只定義了[SalesOrderHeader_test]表上有a.[SalesOrderID]>43659 AND a.[SalesOrderID]53660過(guò)濾條件,但是根據(jù)語(yǔ)義分析,SQL知道這個(gè)條件在[SalesOrderDetail_test]上也為真。所以SQL選擇先把這個(gè)條件過(guò)濾然后再做join。這樣能夠大大降低join的cost
在這一步SQL預(yù)估返回50561條記錄,實(shí)際返回50577條。cost是0.127,也不高
步驟b(第4行):將a1和a2兩步得到的結(jié)果集做一個(gè)join。因?yàn)镾QL通過(guò)預(yù)估知道這兩個(gè)結(jié)果集比較大,所以他直接選擇了Hash Match的join方法。
SQL預(yù)估這個(gè)join能返回50313行,實(shí)際返回50577行。因?yàn)镾QL在兩張表的[SalesOrderID]上都有統(tǒng)計(jì)信息,所以這里的預(yù)估非常準(zhǔn)確
這一步的cost等于totalsubtreecost減去他的子步驟,0.715-0.202-0.127=0.386。由于預(yù)估值非常準(zhǔn)確,可以相信這里的cost就是實(shí)際每一步的cost
步驟c(第3行):在join返回的結(jié)果集基礎(chǔ)上算count(*)的值這一步比較簡(jiǎn)單,count(*)的結(jié)果總是1,所以預(yù)測(cè)值是正確的。
其實(shí)這一步的cost是根據(jù)上一步(b)join返回的結(jié)果集大小預(yù)估出來(lái)的。我們知道步驟b的預(yù)估返回值非常準(zhǔn)確,所以這一步的預(yù)估cost也不會(huì)有什么大問(wèn)題
這棵子樹的cost是0.745,減去他的子節(jié)點(diǎn)cost,他自己的cost是0.745-0.715=0.03。是花費(fèi)很小的一步
步驟b(第2行):將步驟c返回的值轉(zhuǎn)換為int類型,作為結(jié)果返回
這一步是上一步的繼續(xù),更為簡(jiǎn)單。convert一個(gè)值的數(shù)據(jù)類型所要的cost幾乎可以忽略不計(jì)。所以這棵子樹的cost和他的子節(jié)點(diǎn)相等,都是0.745。
也就是說(shuō),他自己的cost是0
通過(guò)這樣的方法,用戶可以了解到語(yǔ)句的執(zhí)行計(jì)劃、SQLSERVER預(yù)估的準(zhǔn)確性、cost的分布
最后說(shuō)一下:不同SQLSERVER版本,不同機(jī)器cost可能會(huì)不一樣,例如SQL2005 ,SQL2008
您可能感興趣的文章:
  • SQL Server自動(dòng)更新統(tǒng)計(jì)信息的基本算法
  • sqlserver 統(tǒng)計(jì)sql語(yǔ)句大全收藏
  • SQLSERVER語(yǔ)句的執(zhí)行時(shí)間顯示的統(tǒng)計(jì)結(jié)果是什么意思
  • 淺談SQL Server中統(tǒng)計(jì)對(duì)于查詢的影響分析
  • SQLServer2005 中的幾個(gè)統(tǒng)計(jì)技巧
  • SQL Server統(tǒng)計(jì)信息更新時(shí)采樣百分比對(duì)數(shù)據(jù)預(yù)估準(zhǔn)確性的影響詳解

標(biāo)簽:重慶 昭通 貴州 新鄉(xiāng) 拉薩 呼和浩特 上海 江蘇

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《SQLSERVER收集語(yǔ)句運(yùn)行的統(tǒng)計(jì)信息并進(jìn)行分析》,本文關(guān)鍵詞  SQLSERVER,收集,語(yǔ)句,運(yùn),行的,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《SQLSERVER收集語(yǔ)句運(yùn)行的統(tǒng)計(jì)信息并進(jìn)行分析》相關(guān)的同類信息!
  • 本頁(yè)收集關(guān)于SQLSERVER收集語(yǔ)句運(yùn)行的統(tǒng)計(jì)信息并進(jìn)行分析的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章