1. 程式人生 > >程式設計師眼中的 SQL Server-執行計劃教會我如何建立索引?

程式設計師眼中的 SQL Server-執行計劃教會我如何建立索引?

先說點廢話

以前有 DBA 在身邊的時候,從來不曾考慮過資料庫效能的問題,但是,當一個應用程式從頭到腳都由自己完成,而且資料庫面對的是接近百萬的資料,看著一個頁面載入速度像烏龜一樣,自己心裡真是有種挫敗感。程式碼的優化問題,這是屬於程式設計師的職責範圍之內,對於我來說,這一方面比較好探查些,因為都是自己熟悉的,用 EF 或 SQL Server Profiler 跟蹤一下程式程式碼產生的 SQL,如果有問題,直接優化程式程式碼就可以了,如果 SQL 沒問題,那就得優化資料庫了,對於我來說,這是一個無人區。

前兩天,自己瞎搞了一個測試:程式設計師眼中的 SQL Server-非聚集索引能給我們帶來什麼?

,因為對索引不是很熟悉,所以測試得到結果沒有任何價值,甚至有些誤導人,這邊說聲抱歉,在哪跌倒在哪爬起來。

應用場景

還是用商品表(Product)作為示例,表結構如下:

存在這樣一種業務場景:獲取某個供應商(ProviderID),狀態為已售(State 為 1)的商品列表,排序方式為生產日期(ProduceTime)降序,有可能我們應用程式在顯示資料的時候用到分頁,這邊我們查詢前 100 行。翻譯為 SQL 程式碼:

SELECT TOP 100 
[ID],
[Name],
[Remarks],
[ProviderID],
[ProduceTime],
[State]
FROM [TestDB].[dbo].[Product]
WHERE [ProviderID]=1 AND [State]=1
ORDER BY [ProduceTime] DESC

上面這個業務場景,在我們一般的應用程式中基本上都會遇到,有時候資料量不是很大的時候,我們一般不會做任何資料庫優化,但是你看了下面的實踐,你是否應該考慮下,為你現在的資料庫加個索引呢?

SQL Server 執行計劃

SQL Server 執行計劃,是我們分析 SQL 執行情況的一大利器,通過它,我們也可以很方面的檢視索引的執行,在實踐之前,需要了解一些必備技能,以下知識點摘自-看懂 SqlServer 查詢計劃

SQL Server 有二種索引:聚集索引和非聚集索引。二者的差別在於:【聚集索引】直接決定了記錄的存放位置, 或者說:根據聚集索引可以直接獲取到記錄。【非聚集索引】儲存了二個資訊:1.相應索引欄位的值,2.記錄對應聚集索引的位置(如果表沒有聚集索引則儲存記錄指標)。 因此,如果能通過【聚集索引】來查詢記錄,顯然也是最快的。

SQL Server 會有以下方法來查詢您需要的資料記錄:

  1. 【Table Scan】:遍歷整個表,查詢所有匹配的記錄行。這個操作將會一行一行的檢查,當然,效率也是最差的。
  2. 【Index Scan】:根據索引,從表中過濾出來一部分記錄,再查詢所有匹配的記錄行,顯然比第一種方式的查詢範圍要小,因此比【Table Scan】要快。
  3. 【Index Seek】:根據索引,定位(獲取)記錄的存放位置,然後取得記錄,因此,比起前二種方式會更快。
  4. 【Clustered Index Scan】:和【Table Scan】一樣。注意:不要以為這裡有個Index,就認為不一樣了。 其實它的意思是說:按聚集索引來逐行掃描每一行記錄,因為記錄就是按聚集索引來順序存放的。 而【Table Scan】只是說:要掃描的表沒有聚集索引而已,因此這二個操作本質上也是一樣的。
  5. 【Clustered Index Seek】:直接根據聚集索引獲取記錄,最快!

所以,當發現某個查詢比較慢時,可以首先檢查哪些操作的成本比較高,再看看那些操作在查詢記錄時, 是不是【Table Scan】或者【Clustered Index Scan】,如果確實和這二種操作型別有關,則要考慮增加索引來解決了。 不過,增加索引後,也會影響資料表的修改動作,因為修改資料表時,要更新相應欄位的索引。所以索引過多,也會影響效能。 還有一種情況是不適合增加索引的:某個欄位用0或1表示的狀態。例如可能有絕大多數是1,那麼此時加索引根本就沒有意義。 這時只能考慮為0或者1這二種情況分開來儲存了,分表或者分割槽都是不錯的選擇。

應用分析

我們先不建任何索引(除了主鍵 ID 的聚集索引),來看一下上面 SQL 程式碼,在 SQL Server 執行計劃中的執行情況:

可以看到,查詢開銷基本上被 SORT 霸佔了,看到這種情況,按照正常的思維,我們首先考慮的是為 ProduceTime 建立一個非聚集索引,然後按照 DESC 排序,但有時候我們要沉下心思考一下,是不是用 ID 排序會更好呢?因為在 Product 表中,ID 為自增欄位,ProduceTime 在新增的時候獲取的是當前時間,在 SQL 排序中,其實 ID 和 ProduceTime 的排序效果是一樣的,但是執行效能方面確實天壤之別,我們看一下執行計劃就知道了:

從上面的執行計劃中,我們可以很直觀的看出差別,所以在寫 SQL 的時候,一定要慎重啊,這邊為了方便展示,我們還是以 ProduceTime 欄位進行排序,按照 ID 排序,雖然沒有了 SORT 效能開銷,但是發現查詢記錄為“Clustered Index Scan”,這是全表查詢的意思,我們理想的應該是“Index Seek”或者“Clustered Index Seek”,因為這種是按照索引查詢,速度最快。按照我們程式設計師的理解,應該建立一個非聚集索引,比如下面 IX_Product_Provider_State 索引:

建立好之後,我們再來執行一下 SQL 程式碼:

“Key Lookup(Clustered)”記錄,其實還是全表進行查詢,預設通過聚集索引(PK_Product),我們可能會有疑問,索引就是按照查詢及排序方式建立的啊,為什麼還是這種情況?這時候我們看一下 SELECT 後面的欄位就知道了,我們查詢顯示的是 Product 表中所有欄位,但是 IX_Product_Provider_State 非聚集索引,只是針對的查詢條件欄位,並沒有吧查詢顯示欄位包含進來,在建立索引視窗中,“索引鍵 列” TAB 的旁邊有個“包含性 列”,我們把其他顯示欄位加進來,看下執行效果:

“Index Seek”,這就是我們想要的效果,其實關於索引的建立有很多的現實問題,比如組合欄位索引和單個欄位索引有何不同?就像上面示例中的查詢用例,如果 ProduceTime 排序在其他查詢條件中也存在,是不是應該拉出來建立一個索引?還是像上面一樣,和查詢條件一起建立一個組合欄位索引?還有一種情況就是,在一個應用程式查詢中,存在單個欄位的查詢,也存在組合欄位的查詢,那這時候我們是建立單個欄位索引?還是建立組合欄位索引呢?這幾個問題,你建立一下索引,然後用“ SQL 執行計劃”試試就知道了。

總結

針對上面的查詢用例,我個人覺得,最好的方案是:排序欄位使用 ID,按照實際應用場景,提取出需要查詢的欄位,避免 SELECT *,這樣會減少在新增“包含性 列”的欄位,建立 IX_Product_Provider_State 非聚集索引,索引欄位為:ProviderID 和 State,如果 State 的值不是多變的(比如值為 1 和 0),儘量不要建立 State 欄位的非聚集索引。

做完這些,你會發現,你的應用程式像飛的一樣。

ps:我要飛得更高。。。

參考資料:

相關推薦

瞭解Sql Server執行計劃 看懂SqlServer查詢計劃 程式設計師眼中SQL Server執行計劃教會如何建立索引

閱讀目錄 如何啟動執行計劃 執行計劃結果要看什麼 Sql Server的五種查詢方式 檢視更具體的執行過程 參考資料   前一篇總結了Sql Server Profiler,它主要用來監控資料庫,並跟蹤生成的sql語句。但是隻拿到生成的sql語句沒有什麼用

程式設計師眼中SQL Server執行計劃教會如何建立索引

先說點廢話 以前有 DBA 在身邊的時候,從來不曾考慮過資料庫效能的問題,但是,當一個應用程式從頭到腳都由自己完成,而且資料庫面對的是接近百萬的資料,看著一個頁面載入速度像烏龜一樣,自己心裡真是有種挫敗感。程式碼的優化問題,這是屬於程式設計師的職責範圍之內,對於我來說,這一方面比較好探查些,因為都是自己熟悉的

Sql Server執行計劃的緩存機制

機制 大致 sql語句 color 內存 存儲過程 image 語法檢查 轉換 Sql查詢過程       當執行一個Sql語句或者存儲過程時, Sql Server的大致過程是 1. 對查詢語句進行分析,將其生成邏輯單元,並進行基本的語法檢查 2. 生成查詢樹(會將

SQL Server控制執行計劃

為了提高效能,可以使用提示(hints)特性,包含以下三類: 查詢提示:(query hints)告知優化器在整個查詢過程中都應用某個提示 關聯提示:(join hints)告知優化器在查詢的特定部分使用指定的關聯演算法 表提示:(table hints)告知優化器使用表掃描還是表上特定的索引 這是非

SQL Server實際執行計劃COST"欺騙"案例

但是需要再次注意,執行計劃在欺騙你,首先,它意味著只調用了UDF一次,其實不是這樣。其次,從成本(Cost)來看,你可能會認為0%是向下舍入影響,因為單次執行函式的開銷如此之小,以至於執行100,000次的成本也很小。但如果你檢查執行計劃的功能迭代器的屬性,你會發現所有的操作代價和子樹代價實際的估計為0,這是

SQL Server執行計劃教會如何建立索引

因為對索引不是很熟悉,所以測試得到結果沒有任何價值,甚至有些誤導人,這邊說聲抱歉,在哪跌倒在哪爬起來。 應用場景 還是用商品表(Product)作為示例,表結構如下: 存在這樣一種業務場景:獲取某個供應商(ProviderID),狀態為已售(State 為 1)的商品列表

瞭解Sql Server執行計劃

  前一篇總結了Sql Server Profiler,它主要用來監控資料庫,並跟蹤生成的sql語句。但是隻拿到生成的sql語句沒有什麼用,我們可以利用這些sql語句,然後結合執行計劃來分析sql語句的效能問題,這才是我們的最終目的,那麼如何使用執行計劃呢?我準備從以下幾點來總結。 如何啟動執行計劃

程式設計師眼中SQL Server非聚集索引能給我們帶來什麼?

寫在前面 最近在做的一個專案,頁面訪問的時候很慢(大概幾秒鐘的樣子),然後用日誌記錄的方式,來排查這個問題,最後發現是 Entity Framework 初始化的一個坑(大概要花 6-7 秒),詳見:《來,給Entity Framework熱熱身》,但是除了這個問題,還發現當一些使用者資料量很大的時候,訪問也

sql server 資料庫優化--顯示執行計劃 你真的知道索引使用???

首先在PRID欄位上建立非聚集索引。 CREATE UNIQUE NONCLUSTERED INDEX UNC_PRID ON PerformanceIssue (PRID) GO 執行下面語句並檢視執行計劃的結果。 Select PRID, PRCode, PRDesc From Perform

sql Server如何執行批量插入和批量刪除

emc pcs -- frog bps eno bbu ads spc 平時我們sql server執行查詢語句都是通過 insert into 表名(字段名,字段名) values(插入值,插入值) --單條插入語句--- insert into Reader(read

SQL Server 運行計劃操作符具體解釋(2)——串聯(Concatenation )

-s 而且 article font order close 格式 聚集索引 content 本文接上文:SQL Server 運行計劃操作符具體解釋(1)——斷言(Assert)前言: 依據計劃。本文開始講述另外一個操作符串聯(Concatenation)。讀者能夠依

程式設計師眼中的瀏覽器是什麼樣的?IE:有本事你卸了

瀏覽器之爭從上個世紀就已經開始,已經持續了很長的時間。到目前為止,競爭依然激烈。在很多年前,IE還是最主流的web瀏覽器。但現在形勢早已完全不同了,不知道大家還有多少人在用IE瀏覽器?今天,小編向大家分享一下針對IE的搞笑圖片,只是逗樂而已,希望大家看的開心! 1、當瀏覽器化作一種槍,你喜歡用哪

程式設計師眼中的瀏覽器是什麼樣的?IE:有本事你就把卸了啊

瀏覽器之爭從上個世紀就已經開始,已經持續了很長的時間。到目前為止,競爭依然激烈。在很多年前,IE還是最主流的web瀏覽器。但現在形勢早已完全不同了,不知道大家還有多少人在用IE瀏覽器?今天,小編向大家分享一下針對IE的搞笑圖片,只是逗樂而已,希望大家看的開心! 1、當瀏覽器化作一種槍,你喜歡用哪

黑馬程式設計師----Java基礎之多執行

------- <a href="http://www.itheima.com" target="blank">android培訓</a>、<a href="http://www.itheima.com" target="blank">java培訓</a&g

使用oracle sql profile固定執行計劃

  2013-02-05 16:19:36 標籤: oracle sql profile 版權宣告:原創作品,如需轉載,請與作者聯絡。否則將追究法律責任。 使用sql profile固

程式設計師眼中的能者多勞,是「坑」麼?

點選上方“程式人生”,選擇“置頂公眾號” 第一時間關注程式猿(媛)身邊的故事 作者 上海小胖 原文標題 能者多勞,等待上帝的眷顧,若是個坑,我寧願跳進去再爬上來 如需轉載,請聯絡我們。 目錄: 1. 只有“能者”才能多勞 2. “能者”喜

淺談SQL Server內部執行機制

        對於已經很熟悉T-SQL的讀者,或者對於較專業的DBA來說,邏輯的增刪改查,或者較複雜的SQL語句,都是非常簡單的,不存在任何挑戰,不值得一提,那麼,SQL的哪些方面是他們的挑戰 或者軟肋呢? 那就是sql優化。然而,要向成為一個好的Sql優化高手,首

SSIS最佳實踐:SQL Server提升執行效能

SQL Server整合服務(SQL Server Integration Services,SSIS)在其前輩DTS(Data Transformation Services,資料轉換服務)的基礎上進步了不少,從可用性、效能和並行等方面來說,它已經成長為一個企業級ETL(Extractio

程式設計師眼中的2007 尋找軟體開發利器

                 軟體開發生命週期包括需求分析、設計、開發、測試、交付部署等各個階段,以及貫穿在整個開發過程的軟體開發專案管理環節,2006年,在每一個階段都出現了令人眼花繚亂的技術與應用,同時這些技術還將進一步影響2007年的發展,令人充滿期待。  建模和開發工具平臺  UML在版本升級到2

一個女程式設計師眼中程式設計師

是的,我是一名程式設計師。很多人說好炫酷,女程式設計師,聽起來好厲害。實不相瞞,入行的時候,我也是這麼覺得的。我畢業於一所師範學院,就業的主要的輸出方向還是教師,公務員,銀行職員。這麼說吧,就業統計的時候,哪位老師門下拿到銀行offer的學生多,都會比較有面子