SQL Server調優系列玩轉篇三(利用索引提示(Hint)引導語句最大優化運行)

前言html

本篇繼續玩轉模塊的內容,關於索引在SQL Server的位置無須多言,本篇將分析如何利用Hint引導語句充分利用索引進行運行,一樣,仍是但願紮實掌握前面一系列的內容,才進入本模塊的內容分析。算法

閒言少敘,進入本篇的內容。數據庫

技術準備多線程

數據庫版本爲SQL Server2012,利用微軟的之前的案例庫(Northwind)進行分析,部份內容也會應用微軟的另外一個案例庫AdventureWorks。工具

相信瞭解SQL Server的朋友,對這兩個庫都不會太陌生。post

1、並行Hint提示 (MAXDOP N Hint)性能

在當前多核超線程的今天,並行運算已經不算什麼稀罕了,因此在SQL Server中也有它本身的並行運算符,來充分的利用現有硬件資源,最大限度的提高運行效率。學習

在本系列中有兩篇文章專門介紹關於SQL Server的並行運算,能夠點擊查看:SQL Server並行運算總結SQL Server並行運算總結篇二優化

因此,在Hint中也給出了關於並行運算的提示:MAXDOP N Hint,這個Hint仍是常常用的,尤爲索引操做的時候,爲了縮短操做時間,咱們經常會最大限度的利用並行運算。url

另外,此Hint會優先於數據庫級別的配置選項。也就說盡管在數據庫中設置了MAXDOP 1(強制順序運行),若是使用了此Hint也會忽略數據庫設置的。

固然,並行運算雖然大部分狀況能提高運行效率,可是也非絕對,咱們知道多線程的操做是須要維護線程之間的數據交換和執行順序等,全部有時候多線程的執行並不必定會單線程效率高。

來看個例子:

SELECT [KEY],[DATA]
FROM TestMaxDopTable
WHERE DATA<1000
OPTION(MAXDOP 1)


SELECT [KEY],[DATA]
FROM TestMaxDopTable
WHERE DATA<1000
OPTION(MAXDOP 4)

上面爲串行運算,下面爲4線程的並行運算。

固然,此處幾線程運算能夠本身設定,最大值推薦爲當前系統配置的邏輯核數,固然設置大了也能夠只不過沒用罷了。

 二、索引Hint提示 (INDEX  Hint)

所謂的索引Hint提示,就是強制查詢優化器爲一個查詢語句執行掃描或者使用一個指定的索引。

此方式,是咱們在調優中常常用到的一種方式,不少時候咱們建立的索引是失效的,固然,大部分狀況下失效的緣由是建立索引不穩當致使的,可是有一些狀況下,須要咱們來指導下T-SQL的運行方式,這時候就是索引Hint的使用場景了。

固然,這裏能利用索引提示的前提就是當前表存在索引了,若是是堆表的狀況,根本就談不上了索引提示了,只能經過表掃描獲取數據了。

來看看這個提示的用法:WITH(INDEX(N))

這裏的N就是索引的在該表中索引順序排序號了,來看一張表中的索引序列號:

SELECT * FROM SYS.indexes
WHERE OBJECT_NAME(object_id)='Orders'

能夠看到,該表中存在十個索引,依次排序以後,就是從1至10,第一個就是彙集索引(主鍵)了,而後是非彙集索引。

因此,咱們上面的N的值就是這個數字了,指定幾就是要求用哪一個索引了。

來看個腳本:

SELECT OrderID,CustomerID
FROM Orders WITH(INDEX(1)) WHERE ShipPostalCode=N'99362'

SELECT OrderID,CustomerID
FROM Orders WITH(INDEX(9)) WHERE ShipPostalCode=N'99362'

看到了,上面的例子中咱們選了兩個索引:一個編號1的彙集索引PK_Orders,一個編號爲9的非彙集索引了ShipPostalCode。固然,有興趣也能夠玩玩其它幾個索引。

咱們順便來分析下這個語句的索引用法:

首先從查詢條件來看,咱們是根據ShipPostalCode進行查詢,因此最好在該列中被索引所覆蓋,這樣在數據量大的狀況下,查詢優化器就能夠採用索引查找(Index Seek)了,因此,這裏咱們選擇了第9個非彙集索引,恰巧覆蓋該列值,從上面的查詢計劃也能夠看出,採用該索引Hint提示後查詢開銷從69%提高至3%...可是因爲這個非彙集索引沒有包含CustomerID列,因此不得不又引入書籤查找(key Lookup)來獲取該列值,而且這個書籤查找消耗還比較大:60%,因此最佳的方式就是將該索引Include進CustomerID列。

固然,此方式用起來可能很不爽,由於咱們在使用的時候須要查找當前表中的各個索引的排序號。

因此,咱們最推薦也是最經常使用的方式是這樣:

WITH(INDEX('IndexName'))

 

就是咱們直接指定索引名稱既能夠,來看個例子:

SELECT OrderID,CustomerID
FROM Orders WITH(INDEX(CustomersOrders)) WHERE ShipPostalCode=N'99362'

看起來,簡單的多了,由於索引的名字咱們直接能看到,來看看咱們將這個查詢語句指定到這個非彙集索引CustomersOrders上的執行計劃。

來看看這個查詢計劃:丫的!.....查詢開銷直接飆升到100%......緣由很簡單:這個非彙集索引和這個查詢一毛錢關係....可是咱們卻強制的指定該語句利用索引執行....

首先非彙集索引包含的列爲:[OrderID],[CustomerID]

咱們要獲取的值爲按照ShipPostalCode進行篩選,因此要獲取結果就必須按照這個非彙集索引進行一次掃描(Index Scan),這個還能夠,畢竟非彙集索引都是有序進行的,可是爲了進行過濾,就必須引入書籤查找(Key Lookup)進行過濾,咱們知道書籤查找爲隨機IO,消耗巨大,因此此次過濾就比如在整張表中隨機的去查找數據同樣,其實效率還不如來一次表掃描(Table Scan)的好,因此此開銷飆升到95%!

 

上面的例子,也是不少新手容易犯的錯誤。

我記得在玩轉模塊的第一篇中,咱們提到過一個利用OPTIMIZE FOR Hint提示 解決一個引入參數而致使的執行計劃評估不許的問題。

文章能夠點擊此處看到:SQL Server調優系列玩轉篇(如何利用查詢提示(Hint)引導語句運行)

咱們來回顧下:

--普通的查詢語句
SELECT OrderID,OrderDate
FROM Orders
WHERE ShipPostalCode=N'51100'

--參數化後的查詢語句
DECLARE  @ShipPostalCode NVARCHAR(50)
SET @ShipPostalCode=N'51100'
SELECT OrderID,OrderDate
FROM Orders
WHERE ShipPostalCode=@ShipPostalCode

徹底相同邏輯的查詢語句,只是下面那個咱們經過參數進行了傳值操做。

咱們只是加了一個參數,SQL Server將相同的查詢語句,有之前的索引查找變成了索引掃描了!

消耗一會兒從46%提高到54%.....這也是咱們寫的語句常常遇到的問題,由於不少狀況下,咱們都是經過傳參來實現該語句的重用性。

可是,爲何加了參數使得查詢性能變差,顯然不是一個好的方式,在第一篇的玩轉篇中,咱們的解決方式是經過OPTIMIZE FOR Hint提示解決。

這裏,咱們再來看一個解決方式,也能夠經過索引Hint來強制該語句指定按照給定的索引進行查找。

方法以下:

--參數化後的查詢語句
DECLARE  @ShipPostalCode NVARCHAR(50)
SET @ShipPostalCode=N'51100'
SELECT OrderID,OrderDate
FROM Orders WITH(INDEX(ShipPostalCode)) WHERE ShipPostalCode=@ShipPostalCode

是否是一個很帥的方式。

但願你能理解這些個方式的好處,算做拋磚引玉了。 

 

結語

此篇文章先到此吧,到此玩轉篇已經三篇了,關於SQL Server調優工具Hint的使用還有不少內容,後續依次介紹,有興趣的童鞋能夠提早關注。

有問題能夠留言或者私信,隨時恭候有興趣的童鞋加入SQL SERVER的深刻研究。共同窗習,一塊兒進步。 

 

文章最後給出前面幾篇的鏈接,如下內容基本涵蓋咱們平常中所寫的查詢運算的分解以及調優內容項,皆爲原創........

第一個基礎模塊注重基礎內容的掌握,共分7篇文章完成,內容涵蓋一系列基礎運算算法,詳細分析瞭如何查看執行計劃、掌握執行計劃優化點,並一一列舉了平常咱們日常所寫的T-SQL語句所會應用的運算符:

SQL Server調優系列基礎篇

SQL Server調優系列基礎篇(經常使用運算符總結)

SQL Server調優系列基礎篇(聯合運算符總結)

SQL Server調優系列基礎篇(並行運算總結)

SQL Server調優系列基礎篇(並行運算總結篇二)

SQL Server調優系列基礎篇(索引運算總結)

SQL Server調優系列基礎篇(子查詢運算總結)

 

第二個進階模塊注重SQL Server執行T-SQL語句的時候一些內幕解析,共分爲5篇文章完成,其中包括:查詢優化器的運行方式、運行時幾個優化指標值檢測,統計信息、利用索引等一系列內容。經過這塊內容讓咱們瞭解SQL Server爲咱們所寫的T-SQL語句如何進行優化及運行的。

SQL Server調優系列進階篇(查詢優化器的運行方式)

SQL Server調優系列進階篇(查詢語句運行幾個指標值監測)

SQL Server調優系列進階篇(深刻剖析統計信息)

SQL Server調優系列進階篇(如何索引調優)

SQL Server調優系列進階篇(如何維護數據庫索引)

 

第三個玩轉模塊重點跟進特定的問題進行特定的提示(Hints),基於前兩個模塊進行的分析。

 SQL Server調優系列玩轉篇(如何利用查詢提示(Hint)引導語句運行)

SQL Server調優系列玩轉篇二(如何利用匯聚聯合提示(Hint)引導語句運行)

 

若是您看了本篇博客,以爲對您有所收穫,請不要吝嗇您的「推薦」。

相關文章
相關標籤/搜索