索引的重要性

来源:http://www.cnblogs.com/zhuancloud/archive/2017/02/16/6402126.html
-Advertisement-
Play Games

前面很多篇不管CPU、記憶體、磁碟、語句等等等都提到了索引的重要,我想剛剛開始學資料庫的在校學生都知道索引對語句性能的重要性。但他們可能不知道,對語句的重要性就是對系統的重要性! 開篇小測驗 開篇小測驗 下麵這樣一個小SQL 你該怎麼樣添加最優索引 你是否一眼就能看出來呢? 答案將在文章中逐步揭曉~~ ...


前面很多篇不管CPU、記憶體、磁碟、語句等等等都提到了索引的重要,我想剛剛開始學資料庫的在校學生都知道索引對語句性能的重要性。但他們可能不知道,對語句的重要性就是對系統的重要性!

 

  • 開篇小測驗

  下麵這樣一個小SQL 你該怎麼樣添加最優索引

  兩個表上現在只有聚集索引

  bigproduct 表上已經有聚集索引 ProductID

 

  bigtransactionhistory 表上已經有聚集索引 TransactionID

  

select p.productnumber,p.reorderpoint,th.Quantity
from bigproduct as p
join bigtransactionhistory as th on th.productid=p.productid and th.TransactionDate > p.SellStartDate
where p.name in ('LL Crankarm1000','ML Crankarm1000') and th.TransactionDate > '2010-01-01'

 

 

 

  你是否一眼就能看出來呢?

  

  答案將在文章中逐步揭曉~~~

  • 簡單粗暴的添加索引

  看過我前面文章的看官們一定會發現我很喜歡用“簡單粗暴”這個詞,一是因為辭彙量小文筆也差,真心用不出高大上的詞兒! 再一個,你們不喜歡簡單粗暴麽~~乾貨最重要,不是麽?

  

  首先我們看一下沒有優化前的執行計劃

  

  

  

  clustered index scan 這其實就是表掃描,不是table scan 只是因為表上有聚集索引

  可以看出這個查詢倆表都使用了表掃描!  

  

  where 條件添加索引

  首先大多數人都知道 where 條件中的欄位需要添加索引! 我們添加一下看看效果創建 

  在 bigproduct 表上創建 name 列索引 ,在bigtransactionhistory表上創建 TransactionDate 列索引。

  再次執行語句看一下效果!

  

  

  

  添加where索引以後可以看到以下幾個現象

  1. bigproduct 從原來的clustered index scan 變成 index seek
  2. 另外多出來個KEY Lookup(clustered)
  3. bigproduct 上添加的索引起了作用,邏輯讀bigproduct 由 601 變成 10。
  4. bigtransactionhistory 沒啥變化啊 還是clustered index scan

  

  解釋一下出現的現象 : 首先一點bigproduct 邊添加的where 條件索引,起到了作用,執行的時候不是全表掃描了,邏輯讀有明顯的下降,出現的 KEY Lookup 是因為選擇(select)的列,在索引中沒有,而需要通過聚集索引再查找一次,再找一次也意味著多一部分開銷!

  那麼同樣添加了where 條件索引的bigtransactionhistory 表為什麼沒起作用呢? 那是因為SQL優化器在選擇計劃的時候認為,不使用TransactionDate 列索引查找效率會更好! 

  真的麽? 我們來驗證一下,通過指定選擇索引,來讓優化器選擇索引查找!

  

 

  

 

   強制使用索引以後,可以看出邏輯讀由 14W 變成1961W,語句時間也變得很長,這就是優化器為什麼不選用你加的索引!優化器還是很智能的吧。

 

  高能預警:優化器可不是什麼時候都這麼智能的...由於緩存計劃或優化器抽風等原因,也會出現優化器用了這種索引,導致你的語句奇慢,讀飆升直接影響到你的記憶體、磁碟、CPU資源!另外如果這樣一條語句是系統中一條很頻繁運行的語句,你的系統就掛了!沒錯就掛了!這就是開篇拋出的問題就是因為一條語句!

 

 

  消滅Key Lookup 添加select 欄位

   這就是傳說中的覆蓋索引! 

   看到執行計劃中存在Key Lookup 而且消耗占比很高,如上面強制索引的計劃,那麼我們就要想到的 在索引中包含那些SELECT 的列!如果消耗低,邏輯讀少,如上面bigproduct 表中的Key Lookup 就可以忽略(如果你追求完美,也一樣優化就可以了)。

   包含列的圖形化創建 : 

   

   

   語句創建就是 :

   

CREATE NONCLUSTERED INDEX TransactionDate
ON [dbo].[bigTransactionHistory] ([TransactionDate])

------INCLUDE 就是包含列
INCLUDE ([ProductID],[Quantity])
GO

 

 

 

 

   下麵我們添加一下看看效果 :

   

 

   

 

  添加select 索引欄位後可以看出的現象:

  1. 優化器自己選擇了index seek
  2. bigtransactionhistory占比最高的Key Lookup消失了
  3. 邏輯讀由原來無索引的14W變成1W
  4. bigtransactionhistory表還提示缺少索引?

   

   通過優化索引添加select 欄位,我們看出語句又一次得到了提升 bigtransactionhistory 從表掃描變成索引查找,邏輯讀由14W變成 1W!這是一個質的飛躍啊!

 

   那為什麼還提示缺少索引呢? 創建一下試試吧!

  索引再優化加入表關聯列

  按照提示我們創建索引 : 和上一個索引的不同 ProductID 列由包含列變成了索引列!

USE [AdventureWorks2012]
GO
CREATE NONCLUSTERED INDEX ProductID_TransactionDate
ON [dbo].[bigTransactionHistory] ([ProductID],[TransactionDate])
INCLUDE ([Quantity])

 

 

  我們看一下效果:

  

 

  

 

  再次優化索引以後可以看到以下幾個現象

  1. bigtransactionhistory表還是索引查找index seek
  2. bigtransactionhistory依然沒有了Key Lookup
  3. 兩表關聯的hash join 變成了nested loops
  4. 並行計劃變成了串列
  5. 邏輯讀又從1W 變成18

 

  又一次質的飛躍!讀從原來的14W 變成1W 又變成18,這樣大大減少了記憶體和IO的消耗,另外並行計劃也變成了串列,無疑又減少了大量CPU的消耗!語句時間,我想這裡就不用多說了吧?

  

  高能預警:這裡所說的hash join,並行變串列,不懂的朋友可以在百度自行學習,這裡只是針對當前語句的情況,不能一概而論!

 

 

 

  精簡你的索引

  大家都知道,索引會導致update、insert、delete操作變慢!那麼儘量精簡你的索引就是一個很重要的話題了!

   上面的優化過程中我們創建了幾個索引,以bigTransactionHistory為例來看一下:

  

   腳本這裡就不貼了,其實我們最後創建的索引 ProductID_TransactionDate包含Quantity 已經包含了前兩個索引,而且可以說無論任何類似語句都使用ProductID_TransactionDate包含Quantity 就可以了!

   那麼我們就可以清除前兩個索引!

    

  

 

  至此語句的優化算是結束了,留下的就是bigproduct 依然有一個Key Lookup可以優化,可以仿照上面的繼續優化,這裡就不細說了。語句只是經過了簡單的索引優化就從一輛2手QQ變成了法拉利,是不是很神奇?

  這就是索引的重要性!

 

  開篇小測試你做對了麽?如果沒做對那麼這麼請你自行模擬一個場景再現本篇的話題吧!

 

-----------------------------------------------------------------------------------------------------

  總結 : 往往一個系統的整體緩慢都是因為索引問題導致的,優化索引是對你系統最簡單的保養!

      不要小看一條語句的威力,一條語句足可以讓你的系統徹底無法工作!

     

     一個問題隨之而來語句一條一條漫無目的的優化麽?我怎麼找出系統的問題語句?怎麼樣的一個優先順序? 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Hibernate對資料庫結構提供了較為完整的封裝,Hibernate的O/R Mapping實現了POJO 和資料庫表之間的映射,以及SQL 的自動生成和執行。程式員往往只需定義好了POJO 到資料庫表的映射關係,即可通過Hibernate 提供的方法完成持久層操作。程式員甚至不需要對SQL 的熟 ...
  • mysql的索引是通過B+tree的方式的。B+tree是平衡二叉樹的變種,所以查詢的速度是非常快的。(B+tree :https://zh.wikipedia.org/zh-hans/B%2B%E6%A0%91) 索引主要分為聚集索引和輔助索引: 聚集索引:mysql中的數據是通過主鍵的聚集索引儲 ...
  • SQL優化隨記(一)建表 關鍵字:多表OR單表,索引,分區分表 (1)多表OR單表(寫下個人經驗) 多表的優點(相對單表) 1. 規範,方便管理閱讀; 2. 可優化減少表記錄數量; 3. 可減輕對應表的查詢IO消耗。 多表的缺點(相對單表) 1. 查詢時,需經常使用統計函數,資源消耗較大; 2. 表 ...
  • 本文將為您描述SQL Server會話KILL不掉,一直處於KILLED /ROLLBACK狀態情形淺析,教程操作方法: 今天遇到一個很奇怪的情況,發現一個會話異常,這個會話只是在執行一個簡單的存儲過程,裡面使用了鏈接伺服器(Linked Server)查詢另外一臺伺服器數據(存儲過程裡面沒有任何顯 ...
  • 資料庫事物隔離級別有四種,按照隔離性,由低到高依次是:1.Read Uncommitted 2.Read Committed 3.Repeatable Read 4.Serializable 按照併發性則順序相反。 √: 可能出現 ×: 不會出現 1.Read uncommitted 讀未提交,即在 ...
  • --創建外部表 CREATE EXTERNAL TABLE my_report( last_update string, col_a string) PARTITIONED BY ( par_dt string)ROW FORMAT DELIMITED FIELDS TERMINATED BY ', ...
  • 在cdh集成的solr cloud中,我們可以通過solr管理界面進行查詢,也可以通過java的api進行查詢,但查詢過程中,如果是時間類型的,可能會存在兩者在界面上看上去不一致的問題,兩者時間剛好相差本地的時區。 ...
  • 本文屬於《InfluxDB系列教程》文章系列,該系列共包括以下 16 部分: 系列詳情請看:《InfluxDB系列教程》 最近有很多朋友咨詢在新安裝了InfluxDB後,web頁面無法訪問,在此說下原因和解決方案。 一、問題原因 InfluxDB在0.13版本以後,就預設關閉了web管理頁面,而國內 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...