MS SQL Server 2005 物理查詢處理中的各個(gè)階段()

大家好,我是浪客,和大家分享一些最近我從《Microsoft SQL SERVER 2005技術(shù)內(nèi)幕:T-SQL查詢》書中的心得,終于出“二“了,回應(yīng)很多朋友的需求,今天抽空寫了物理查詢階段,

上文中你真的了解T-SQL邏輯查詢嗎?提到的這種搜索方式,也許很多人不明白(包括我,我看之前簡直感到詫異),很多都想 如果表的記錄有10000000~!#!@條,那每次的CROSS JOIN 將會(huì)長生 m*n的記錄,我們就假設(shè)是1W 1w的平方還是有點(diǎn)點(diǎn)恐怖的,所以實(shí)際存儲(chǔ)引擎并不是如此查詢的,但是講清楚 邏輯查詢很重要,因?yàn)槟鞘俏锢聿樵兊幕A(chǔ),我覺得 理解數(shù)據(jù)庫引擎的查詢處理方式有助于 開發(fā)人員在生產(chǎn)過程中做出正確的選擇。PS:(有朋友說文章很多都“借鑒“別人的例子,我想是好東西用什么例子都不重要吧,只要能分享給大家,我抄都抄過來,再說是我對(duì)書的一些總結(jié),呵呵~,這里要感謝作者Lubor Kollar,他是書中該章節(jié)的作者,是MS SQL SERVER 2005開發(fā)人員)。

那么開始吧,當(dāng)一個(gè)查詢你到達(dá)數(shù)據(jù)庫引擎的時(shí)候 SQL SERVER 執(zhí)行兩個(gè)主要的步驟來產(chǎn)生結(jié)果,一步就是 “查詢編譯”,一個(gè)是“生成查詢計(jì)劃”。首先提一下為什么存儲(chǔ)過程的效率總是比應(yīng)用程序級(jí)別的T-SQL語句來的更迅速,首先拋開網(wǎng)絡(luò)傳輸T-SQL語句的時(shí)間不管,我們利用應(yīng)用程序發(fā)送的T-SQL語句,交個(gè)數(shù)據(jù)庫執(zhí)行,他首先就要對(duì)T-SQL語句進(jìn)行編譯,在SQL中編譯的概念,和我們寫應(yīng)用程序理解應(yīng)該是一致的,包括語法的檢查,代數(shù)化以及查詢優(yōu)化,就像我們的應(yīng)用程序(我是搞.NET的),編譯器對(duì)你的C#代碼進(jìn)行編譯,先檢查語法的錯(cuò)誤,然后生成dlldll 中就包括對(duì)整個(gè)類庫的描述類似于SQL中的執(zhí)行計(jì)劃,回到SQL中,這個(gè)編譯過程當(dāng)然是需要時(shí)間的,所以應(yīng)用程序級(jí)別的T-SQL 交給數(shù)據(jù)庫編譯以后才執(zhí)行,更可惡的是,竟然對(duì)外部傳輸來的T-SQL語句不會(huì)進(jìn)行 “過程緩存”,因?yàn)樗诰幾g后就立即執(zhí)行了,而存儲(chǔ)過程他就已經(jīng)預(yù)先編譯了,也進(jìn)行了查詢的優(yōu)化了,還會(huì)保存在“過程緩存”中,所以推薦使用存儲(chǔ)過程。

下面就來展示一個(gè)例子:

USE Northwind;

SELECT C.CustomerId,COUNT(o.OrderId) AS NumOrders

FROM dbo.Customers AS C

LEFT OUTER JOIN dbo.Orders AS o ON c.CustomerId=o.CustomerId

WHERE c.City='London'

GROUP BY C.CustomerId

HAVING COUNT(o.OrderId)>5

ORDER BY NumOrders;

返回結(jié)果:

EASTC       8

SEVES       9

BSBEV      10

AROUT     13

上次 就有朋友在留言中提到這個(gè)問題 ,下面我們來看看他的執(zhí)行計(jì)劃,到底 邏輯處理 和物理處理 有什么不同.我們點(diǎn)擊 顯示估計(jì)的執(zhí)行計(jì)劃” ,然后找到 最右邊的 Index seek 索引查找,下圖

這是我切下來的圖片,

我們看到 他的Seek 謂詞 [Northwind].[dbo].[Customers].City=N’London’

再看看 我們的查詢 語句的WHERE 部分

WHERE c.City='London'

完全 符合我在 你真的了解T-SQL邏輯查詢嗎? 一問中先說到的 第一個(gè)階段 找到FROM 的表,但是又有一點(diǎn)不同,物理查詢 他會(huì)等到執(zhí)行CROSS 鏈接以后的 記錄,他會(huì)先直接 篩選WHERE 中的記錄 等于  3個(gè) 邏輯 處理階段 連接和 4個(gè)階段WHERE 合并了.至于 這樣有什么好處呢?

我們繼續(xù),首先我們分析 WHERE ,我們先考慮一種情況  如果 是按照 邏輯 執(zhí)行階段的順序,CROSS JOIN 下來的 虛擬表 將是非常恐怖的 .可是 MS 的員工 在邏輯階段 到物理階段的過程中,肯定會(huì)采取一些列手段來優(yōu)化T-SQL 語句,所以 我們聯(lián)想到 先執(zhí)行WHERE 中的 邏輯處理階段 左表中的 結(jié)果 返回

相當(dāng)于 執(zhí)行:

USE Northwind;

SELECT C.CustomerId

FROM dbo.Customers AS C

WHERE c.City='London'

 

他返回的結(jié)果是:

 

AROUT

BSBEV

CONSH

EASTC

NORTS

SEVES

果然和我們 預(yù)想的一樣返回的 行數(shù) 完全和執(zhí)行計(jì)劃中的 估計(jì)行數(shù) : 6 行 吻合,

這樣執(zhí)行的結(jié)果的好處 ,我們自然可以聯(lián)想到,6行的結(jié)果集 再來 CROSS JOIN 就小多了

,下面我們繼續(xù)剛才的分析,接著 自然是 Orders 表的鏈接,

自然

啟用它的ON  條件, (看看Seek 謂詞)

我們?cè)倩剡^來看看 之前說的  物理處理階段,是不是 完全吻合. 之所以要說明白 邏輯階段,(說個(gè)題外話,有興趣的朋友可以去看看Algebrizer,他是T-SQL中的 新組件是 綁定的重要功能,我想對(duì)高數(shù)有研究的朋友可能會(huì)喜歡里面的研究和分析.他取代了2000中的Normalizer組件,在物理 邏輯 級(jí)別提高了T-SQL 效率.)

對(duì)于 后面文章的  優(yōu)化查詢語句 起到了 舉足輕重的作用, 講明了 物理 處理階段和 邏輯處理階段 對(duì)于 存儲(chǔ)引擎是 怎么執(zhí)行T-SQL 有了一定的了解,才能從原理級(jí)別去提高T-SQL ,這也是國內(nèi)很多同行不曾重視的.當(dāng)然本文的下一篇將繼續(xù)我們的研究 -子查詢的精要