日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

SQL Server 调优系列进阶篇 - 查询语句运行几个指标值监测

發(fā)布時(shí)間:2025/5/22 69 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SQL Server 调优系列进阶篇 - 查询语句运行几个指标值监测 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

前言

上一篇我們分析了查詢優(yōu)化器的工作方式,其中包括:查詢優(yōu)化器的詳細(xì)運(yùn)行步驟、篩選條件分析、索引項(xiàng)優(yōu)化等信息。

本篇我們分析在我們運(yùn)行的過(guò)程中幾個(gè)關(guān)鍵指標(biāo)值的檢測(cè)。

通過(guò)這些指標(biāo)值來(lái)分析語(yǔ)句的運(yùn)行問(wèn)題,并且分析其優(yōu)化方式。

通過(guò)本篇我們可以學(xué)習(xí)到調(diào)優(yōu)中經(jīng)常利用的幾個(gè)利器!

廢話少說(shuō),開(kāi)始本篇的正題。

技術(shù)準(zhǔn)備

數(shù)據(jù)庫(kù)版本為SQL Server2008R2,利用微軟的一個(gè)更簡(jiǎn)潔的案例庫(kù)(Northwind)進(jìn)行分析。

?

利器一、IO統(tǒng)計(jì)

通過(guò)這個(gè)IO統(tǒng)計(jì)能為我們分析出當(dāng)前查詢語(yǔ)句所要掃描的數(shù)據(jù)頁(yè)的數(shù)量。這里面有幾個(gè)重要的概念,我們依次分析。

方法很簡(jiǎn)單,一行代碼搞定:

SET STATISTICS IO ON

來(lái)看個(gè)例子

SET STATISTICS IO ON GO SELECT * FROM Person.Contact

這里可以看到這個(gè)語(yǔ)句對(duì)于數(shù)據(jù)表的操作次數(shù),基于數(shù)據(jù)頁(yè)的掃描項(xiàng)。

所謂的數(shù)據(jù)頁(yè)就是數(shù)據(jù)庫(kù)的底層數(shù)據(jù)存儲(chǔ)方式,SQL Server以數(shù)據(jù)頁(yè)的形式存儲(chǔ)表行數(shù)據(jù)。每個(gè)數(shù)據(jù)頁(yè)為8K,

8K=8192字節(jié)-96字節(jié)(頁(yè)頭)-36字節(jié)(行偏移)=8060字節(jié)

也就說(shuō)一個(gè)數(shù)據(jù)頁(yè)存儲(chǔ)的純數(shù)據(jù)內(nèi)容為8060字節(jié)。

我們依次來(lái)解釋上面出現(xiàn)幾個(gè)讀取的概念:

邏輯讀

表示處理查詢所需要訪問(wèn)頁(yè)的總數(shù)。也就是說(shuō)要完成一個(gè)查詢語(yǔ)句需要讀取的數(shù)據(jù)頁(yè)的總數(shù)。

這里的數(shù)據(jù)頁(yè)有可能來(lái)自內(nèi)存,也有可能來(lái)自硬盤(pán)讀取。

物理讀

這個(gè)就是說(shuō)來(lái)自硬盤(pán)讀取的數(shù)據(jù)頁(yè)數(shù)。我們知道SQL Server每次都會(huì)將讀取的數(shù)據(jù)頁(yè)盡可能存在于內(nèi)存中,以方便下一次直接讀取,提升讀取速度。

所以在這里關(guān)于存儲(chǔ)于內(nèi)存中的數(shù)據(jù)頁(yè)下次訪問(wèn)的概率,提出了一個(gè)指標(biāo):緩存命中率

緩存命中率=(邏輯讀—物理讀)/邏輯讀

提出這個(gè)指標(biāo)的提出其實(shí)就是為了衡量?jī)?nèi)存中緩存的數(shù)據(jù)頁(yè)的有效性。比如:假如緩存與內(nèi)存中的數(shù)據(jù)頁(yè)就使用一次就不使用了,對(duì)于這種就應(yīng)該及時(shí)從內(nèi)存中清除掉,畢竟對(duì)于內(nèi)存資源來(lái)說(shuō)是非常昂貴的。應(yīng)該用它來(lái)緩存命中率高的數(shù)據(jù)頁(yè)。

預(yù)讀

預(yù)讀其實(shí)就是SQL語(yǔ)句在優(yōu)化的時(shí)候預(yù)先讀取到內(nèi)存中的數(shù)據(jù)頁(yè)數(shù)。這個(gè)預(yù)先讀取的數(shù)據(jù)頁(yè)是提前評(píng)估出來(lái)的,也就是上一篇我們文章中介紹的查詢優(yōu)化器要做的事情。

當(dāng)然,這些預(yù)讀的數(shù)據(jù)頁(yè)有時(shí)候不是所有的都要用到,但是它基本能涵蓋到查詢用到的數(shù)據(jù)頁(yè)。

這里要提示一下,預(yù)讀數(shù)據(jù)是通過(guò)另外一個(gè)線程進(jìn)行讀取的和語(yǔ)句優(yōu)化線程非用同一線程,并行運(yùn)行,目的是快速獲取數(shù)據(jù),提升查詢獲取的速度。

從這個(gè)指標(biāo)我們可以分析出很多問(wèn)題,來(lái)舉個(gè)例子:

我們新添加一張測(cè)試表,腳本如下

--執(zhí)行下面腳本新生成一張表 SELECT * INTO NewOrders FROM Orders GO --新增加一列 ALTER TABLE NewOrders ADD Full_Details CHAR(2000) NOT NULL DEFAULT 'full details' GO

然后利用如下腳本來(lái)看下這張表的大小

EXEC sp_spaceused NewOrders,TRUE GO

我們可以看到這張表數(shù)據(jù)頁(yè)的總大小為2216KB,我們知道一頁(yè)為8KB,可以推斷出這個(gè)表的數(shù)據(jù)頁(yè)有:

2216(數(shù)據(jù)頁(yè)總大小)/8(一個(gè)數(shù)據(jù)頁(yè)大小)=277頁(yè)

也就是說(shuō)這個(gè)數(shù)據(jù)表有277個(gè)數(shù)據(jù)頁(yè)。

當(dāng)然,我們也可以通過(guò)如下DMV視圖來(lái)查看該頁(yè)的數(shù)據(jù)頁(yè)數(shù)

SELECT * FROM SYS.dm_db_index_physical_stats (DB_ID('Northwind'),object_id('NewOrders'),NULL,NULL,'detailed')

經(jīng)過(guò)上面的分析,

我們可以推測(cè),在查詢這張表做全表掃描的時(shí)候,理論的數(shù)據(jù)頁(yè)的邏輯讀數(shù)就應(yīng)該為277次

通過(guò)如下語(yǔ)句驗(yàn)證下

--先清空緩存數(shù)據(jù),生產(chǎn)機(jī)慎用 DBCC DROPCLEANBUFFERSSET STATISTICS IO ONSELECT * FROM NewOrders

我去...

這里的邏輯讀取為1047頁(yè),和我們上面的推斷277頁(yè)不相符...擦...神馬原因!!!

這里就是我們要分析的數(shù)據(jù)頁(yè)Forwarded record現(xiàn)象造成的。因?yàn)槲覀冊(cè)谛陆⒌谋?#xff0c;在后面新添加的一列數(shù)據(jù):Full_Details,類型為CHAR(2000)的數(shù)據(jù)列,當(dāng)數(shù)據(jù)行中的變長(zhǎng)列增長(zhǎng)使得原有頁(yè)無(wú)法容納下數(shù)據(jù)行時(shí),數(shù)據(jù)將會(huì)移動(dòng)到新的頁(yè)中,并在原位置留下一個(gè)指向新頁(yè)的指針,這就是所謂的: Forwarded record

?

我們可以通過(guò)如下DMV視圖,查看該表的Forwarded Record形成的頁(yè)有多少

SELECT * FROM SYS.dm_db_index_physical_stats (DB_ID(N'Northwind'),object_id('NewOrders'),NULL,NULL,'detailed')

糾正一下:上圖的770數(shù)據(jù)頁(yè)為Forwarded Record頁(yè),非拆分頁(yè)的概念(感謝院友?wy123?指出)。

看到了,這里的Forwarded Record頁(yè)為770頁(yè),那么我們就可以推測(cè)出我們的邏輯讀數(shù)量來(lái)了

277(原數(shù)據(jù)頁(yè))+770(Forwarded Record頁(yè))=1047頁(yè)

所以上面的我們的問(wèn)題就分析出原因了。

我們通過(guò)此表也展示了一個(gè)Forwarded Record頁(yè)的問(wèn)題:會(huì)影響查詢性能。

解決的方式很多種,最簡(jiǎn)單的方式就是重建聚集索引。

CREATE CLUSTERED INDEX orderID_C ON NewOrders(OrderID) GO DROP INDEX NewOrders.orderID_C GO SET STATISTICS IO ON SELECT * FROM NewOrders GO

通過(guò)IO統(tǒng)計(jì)項(xiàng),除了可以分析出上面的Forwarded Record頁(yè)造成的碎片外,更重要的地方使用來(lái)對(duì)比不同查詢語(yǔ)句之間的讀取次數(shù),通過(guò)降低讀取的次數(shù)來(lái)優(yōu)化語(yǔ)句。

?

關(guān)于預(yù)讀的情況,我們?cè)谇懊嬉呀?jīng)分析了,其數(shù)據(jù)時(shí)通過(guò)另外一個(gè)線程在T-SQL查詢語(yǔ)句優(yōu)化的時(shí)候進(jìn)行數(shù)據(jù)的預(yù)加載。

所以這個(gè)線程在預(yù)讀數(shù)據(jù)的時(shí)候其實(shí)是有一個(gè)參考值的,根據(jù)這個(gè)參考值讀取出來(lái)的數(shù)據(jù)才能保證大部分?jǐn)?shù)據(jù)是有用的,也就是提高上面提到的緩存命中率。

關(guān)于這個(gè)參考值,我分析了下,其實(shí)是分為兩中情況分析的。

?

首先、如果是數(shù)據(jù)表為堆表,SQL Server獲取的方式只能通過(guò)全表掃描了。而此方式為了避免重復(fù)讀取,增加消耗,所以一次的預(yù)讀并非讀取一個(gè)數(shù)據(jù)頁(yè),

而是一段物理上的連續(xù)64個(gè)頁(yè)

來(lái)看聯(lián)機(jī)叢書(shū)的官方解釋:

預(yù)讀機(jī)制允許數(shù)據(jù)庫(kù)引擎從一個(gè)文件中讀取最多 64 個(gè)連續(xù)頁(yè) (512KB)。該讀取作為緩沖區(qū)高速緩存中相應(yīng)數(shù)量(可能是非相鄰的)緩沖區(qū)的一次散播-聚集讀取來(lái)執(zhí)行。如果此范圍內(nèi)的任何頁(yè)在緩沖區(qū)高速緩存中已存在,當(dāng)讀取完成時(shí),所讀取的相應(yīng)頁(yè)將被放棄。如果相應(yīng)頁(yè)在緩存中已存在,也可以從任何一端“裁剪”頁(yè)的范圍。

所以,如果我們的表在物理上不是連續(xù)頁(yè),那么讀取次數(shù)就不好怎么確定了。

我們來(lái)看個(gè)堆表的例子

SET STATISTICS IO ON --新建個(gè)測(cè)試表 SELECT * INTO NewOrders_TEST FROM NewOrders SELECT * FROM NewOrders_TEST

這里預(yù)讀的次數(shù)為8次,所以我估計(jì)底層的數(shù)據(jù)頁(yè)肯定不是連續(xù)的。所以造成了多出了3次。

我們可以DBCC IND()進(jìn)行查詢下,來(lái)驗(yàn)證下我的推斷。

DBCC IND('Northwind','NewOrders_TEST',1)

數(shù)據(jù)信息比較多,我將其粘貼到Excel中,然后做了一個(gè)折線圖,其中涂掉的部分其實(shí)是沒(méi)有數(shù)據(jù)頁(yè)的,所以不會(huì)產(chǎn)生一次讀取。

關(guān)于讀取順序標(biāo)示的也有點(diǎn)問(wèn)題,不過(guò)確定的總數(shù)肯定是8次.....

希望這種方式,各位看官能看懂了...希望我也表述明白了。

?

其次、如果表非堆表,也就是說(shuō)存在聚集索引項(xiàng),那么好了,SQL Server很輕松的找到了它預(yù)讀的參考依據(jù):統(tǒng)計(jì)信息。

并且,我們知道數(shù)據(jù)以B-Tree數(shù)存儲(chǔ),讀取的數(shù)據(jù)頁(yè)都存在與葉子節(jié)點(diǎn)。所以基本沒(méi)有了什么連續(xù)讀取的感念。

一個(gè)葉子節(jié)點(diǎn)就是一個(gè)數(shù)據(jù)頁(yè),一個(gè)數(shù)據(jù)頁(yè)就是一次預(yù)讀。

來(lái)看個(gè)例子:

我們將上面的表添加上聚集索引項(xiàng),再一次清空緩存,執(zhí)行查詢,腳本如下

CREATE CLUSTERED INDEX NewOrders_TESTIndex ON NewOrders_TEST(OrderID) GO SELECT * FROM NewOrders_TEST

這里添加了聚集索引,SQL Server仿佛一下看到了救星,根據(jù)統(tǒng)計(jì)信息,預(yù)讀數(shù)據(jù)就可以。

所以如果統(tǒng)計(jì)信息有錯(cuò)誤,就造成了預(yù)讀的亂讀取....然后嚴(yán)重降低了緩存命中率.....然后嚴(yán)重增加了內(nèi)存中換出換入的速度....增加了CPU....

好了,咱們繼續(xù)文章,上面我們提到的這個(gè)預(yù)讀數(shù)據(jù)行,可以在如下DMV中查到。

SELECT * FROM SYS.dm_db_index_physical_stats (DB_ID(N'Northwind'),object_id('NewOrders_TEST'),NULL,NULL,'detailed')

從這個(gè)DMV視圖中可以看到這種表統(tǒng)計(jì)信息為277個(gè)數(shù)據(jù)頁(yè),所以形成了277次預(yù)讀。

但是,事實(shí)這個(gè)數(shù)據(jù)表是279頁(yè),也就是說(shuō)統(tǒng)計(jì)的信息有問(wèn)題,造成了少讀讀取了2個(gè)數(shù)據(jù)頁(yè),而為了彌補(bǔ)這個(gè)統(tǒng)計(jì)過(guò)失就出現(xiàn)了2次物理讀,重新從硬盤(pán)中獲取。?

?

利器二、時(shí)間統(tǒng)計(jì)

關(guān)于時(shí)間統(tǒng)計(jì)這個(gè)很簡(jiǎn)單,就是統(tǒng)計(jì)T-SQL執(zhí)行語(yǔ)句執(zhí)行時(shí)間項(xiàng),包括CPU占用時(shí)間、語(yǔ)句編譯時(shí)間、語(yǔ)句執(zhí)行總時(shí)間等項(xiàng)。

使用方法也很簡(jiǎn)單,一行代碼

SET STATISTICS TIME ON

通過(guò)這個(gè)參數(shù),可以分析出以上信息,其作用主要是用來(lái)對(duì)比查詢語(yǔ)句調(diào)優(yōu)中的執(zhí)行時(shí)間,我們的目標(biāo)就是降低執(zhí)行時(shí)間。

舉例:我們通過(guò)開(kāi)啟時(shí)間統(tǒng)計(jì),來(lái)對(duì)比下,上面的查詢語(yǔ)句,在第一次運(yùn)行和以后運(yùn)行(數(shù)據(jù)已經(jīng)緩存)的時(shí)間對(duì)比,了解下緩存的重要性

再次執(zhí)行的時(shí)間

緩存追蹤(補(bǔ)充于2014年12月25日)

當(dāng)然我們也可以再深入一點(diǎn),如果想查看該部分?jǐn)?shù)據(jù)在內(nèi)存中緩存的明細(xì),可以通過(guò)如下DMV腳本查看

SELECT * FROM sys.dm_os_buffer_descriptors WHERE DB_NAME(database_id)='Northwind' AND page_type='DATA_PAGE' ORDER BY page_id

也可以通過(guò)該DMV分析出各個(gè)庫(kù)在內(nèi)存中占據(jù)的大小比例,腳本如下:

--清除緩存 dbcc dropcleanbuffers --查看緩存內(nèi)容中在內(nèi)存大小 SELECT COUNT(*)*8/1024 as 'Cached Size(MB)' ,CASE database_id WHEN 32767 THEN 'ResourceDB' ELSE DB_NAME(database_id) END AS 'Database' FROM sys.dm_os_buffer_descriptors GROUP BY DB_NAME(database_id),database_id ORDER BY 'Cached Size(MB)' DESC

經(jīng)過(guò)這次查詢,這張表已經(jīng)全部緩存到內(nèi)存里了,因?yàn)檎麖埍砜偣簿?MB的大小

?

?

文章已經(jīng)有點(diǎn)長(zhǎng)度了...先到此吧。

關(guān)于調(diào)優(yōu)內(nèi)容太廣泛,我們放在以后的篇幅中介紹,有興趣的可以提前關(guān)注。

?

參考文獻(xiàn)

  • 微軟聯(lián)機(jī)叢書(shū)讀取頁(yè)
  • 參照書(shū)籍《SQL.Server.2005.技術(shù)內(nèi)幕》系列

?

有問(wèn)題可以留言或者私信,隨時(shí)恭候有興趣的童鞋加入SQL SERVER的深入研究。共同學(xué)習(xí),一起進(jìn)步。

轉(zhuǎn)載于:https://www.cnblogs.com/MuNet/p/5729385.html

總結(jié)

以上是生活随笔為你收集整理的SQL Server 调优系列进阶篇 - 查询语句运行几个指标值监测的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。