MySql索引總結

来源:http://www.cnblogs.com/wxw16/archive/2016/12/04/6131132.html
-Advertisement-
Play Games

索引概念 B+樹索引分為聚集索引和非聚集索引(輔助索引),但是兩者的數據結構都和B+樹一樣,區別是存放的內容。 可以說資料庫必須有索引,沒有索引則檢索過程變成了順序查找,O(n)的時間複雜度幾乎是不能忍受的。我們非常容易想象出一個只有單關鍵字組成的表如何使用B+樹進行索引,只要將關鍵字存儲到樹的節點 ...


索引概念

B+樹索引分為聚集索引和非聚集索引(輔助索引),但是兩者的數據結構都和B+樹一樣,區別是存放的內容。

可以說資料庫必須有索引,沒有索引則檢索過程變成了順序查找,O(n)的時間複雜度幾乎是不能忍受的。我們非常容易想象出一個只有單關鍵字組成的表如何使用B+樹進行索引,只要將關鍵字存儲到樹的節點即可。當資料庫一條記錄里包含多個欄位時,一棵B+樹就只能存儲主鍵,如果檢索的是非主鍵欄位,則主鍵索引失去作用,又變成順序查找了。這時應該在第二個要檢索的列上建立第二套索引。 這個索引由獨立的B+樹來組織。有兩種常見的方法可以解決多個B+樹訪問同一套表數據的問題,一種叫做聚簇索引(clustered index ),一種叫做非聚簇索引(secondary index)。這兩個名字雖然都叫做索引,但這並不是一種單獨的索引類型,而是一種數據存儲方式。對於聚簇索引存儲來說,行數據和主鍵B+樹存儲在一起,輔助鍵B+樹只存儲輔助鍵和主鍵,主鍵和非主鍵B+樹幾乎是兩種類型的樹。對於非聚簇索引存儲來說,主鍵B+樹在葉子節點存儲是指向真正數據行的指針,並且輔助B+樹在葉子節點存儲也是指向真正數據行的指針,而非主鍵B+樹。

InnoDB使用的是聚簇索引,將主鍵組織到一棵B+樹中,而行數據就儲存在葉子節點上,若使用"where id = 14"這樣的條件查找主鍵,則按照B+樹的檢索演算法即可查找到對應的葉節點,之後獲得行數據。若對Name列進行條件搜索,則需要兩個步驟:第一步在輔助索引B+樹中檢索Name,到達其葉子節點獲取對應的主鍵。第二步使用主鍵在主索引B+樹種再執行一次B+樹檢索操作,最終到達葉子節點即可獲取整行數據。

InnoDB存儲引擎是索引組織表,也就是說數據文件本身就是按照B+樹方式存放數據的。Innodb 聚集索引是按照主鍵(primary key)進行聚集,被索引的列其實是主鍵列,如果沒定義主鍵,Innodb會試著使用唯一非空索引Unique Index來代替,如果還找不到,Innodb就會自動創建一個6位元組作為隱藏主鍵然後在上面進行索引聚集。除了主鍵的聚集索引,其他索引(輔助索引)中不會保存行的物理位置,而是保存主鍵的值,所以通過"二級索引"進行查找是先找到主鍵,再找到行,要進行二次索引查找。在InnoDB存儲引擎中,將B+樹索引分為聚集索引和非聚集索引(輔助索引),但是兩者的數據結構都和B+樹一樣,區別是存放的內容。無論是何種索引,每個頁的大小都是16KB,且不能改變。

MyISM使用的是非聚簇索引,非聚簇索引的兩棵B+樹看上去沒什麼不同,節點的結構完全一致只是存儲的內容不同而已,主鍵索引B+樹的節點存儲了主鍵,輔助鍵索引B+樹存儲了輔助鍵。表數據存儲在獨立的地方,這兩顆B+樹的葉子節點都使用一個地址指向真正的表數據,對於表數據來說,這兩個鍵沒有任何差別。由於索引樹是獨立的,通過輔助鍵檢索無需訪問主鍵的索引樹。

圖示清晰的顯示了聚簇索引和非聚簇索引的差異。

Cardinality

並不是所有在查詢條件中出現的列都需要添加索引,對於什麼時候添加B+樹索引,一般的檢驗是,在訪問表中很少一部分行是使用B+樹索引才有意義。查看索引是否是高選擇性的,可以通過SHOW INDEX語句中的Cardinality列來觀察。Cardinality是一個估計值,在實際中,Cardinality/n_rows_in_table應儘可能接近1,如果非常小,那麼需要考慮是否還要建這個索引。

InnoDB中如何統計Cardinality值,索引的更新可能非常平凡,如果每次更新操作時就統計Cardinality值,那麼對資料庫會帶來很大負擔。InnoDB存儲引擎中,Cardinality統計發生在INSERT和UPDATE操作中,不過並不會每次都去統計,它的策略是:

  • 表中的1/16的數據已發生變化。
  • stat_modified_counter > 2000000000。

stat_modified_counter是資料庫發生INSERT和UPDATE操作的計數器,如果每次對錶中的一行數據更新操作,表中的數據幾乎不會有變化,那麼第一種策略就無法試用。所以計數器用來統計操作的次數,如果滿足條件,也會統計Cardinality值。

InnoDB存儲引擎只對8個葉節點進行採樣。採樣的過程為:

  1. 取得B+樹索引中葉節點的數量,即為A。
  2. 隨機取B+樹索引中的8個節點。統計每頁中不同的記錄的個數,即為P1,P2,...,P8。
  3. 根據採樣的信息給出Cardinality值預估值:Cardinality = (P1+P2+...+P8)* A / 8。

註意:如果表足夠小,表的葉節點小於或等於8個,這時即使隨機採樣,也總是採取到這些頁,因此每次的Cardinality值都是一樣的。

B+樹索引的使用

不同應用中B+樹索引的使用

資料庫存在兩種類型的應用:OLTP和OLAP應用。OLTP是傳統關係型資料庫的主要應用,其主要面向基本的、日常的事務處理,例如銀行交易。OLAP是數據倉庫系統的主要應用,支持複雜的分析操作,側重決策支持,並且提供直觀易懂的查詢結果。

在OLTP應用中,查詢操作一般只從資料庫中取得一小部分數據,在這種情況下,建立B+樹索引後,優化器就會使用索引。對於OLAP應用,一般需要訪問表中的大量數據,並根據這些數據來產生查詢的結果,而這些查詢多是分析的查詢,目的是為決策者提供支持。但是對於LOAP中的複雜查詢,需要涉及多表之間的聯接操作,這是索引的添加是有意義的,但是聯接操作使用Hash Join,那麼索引可能又變得不是非常重要。不過在OLAP應用中,通常需要對時間欄位進行索引,這是因為大多數統計需要根據時間維度來進行判斷。

聯合索引

聯合索引是指對錶上的多個列進行索引,又叫複合索引。對於複合索引:Mysql從左到右的使用索引中的欄位,一個查詢可以只使用索引中的一部份,但只能是最左側部分。例如索引是key index (a,b,c)。可以支持a | a,b | a,b,c 3種組合進行查找,但不支持b,c進行查找。當最左側欄位是常量引用時,索引就十分有效。查詢使用索引的條件不同一般組合索引需要按照“最左首碼”來執行查詢,並不是每個列都需要覆蓋,只是從左邊的列開始組合。在選擇組合索引的時候,當前Query 中過濾性最好的欄位在索引欄位順序中排列越靠前越好。

例如有索引key(a,b,c)

  • where a=xx and b=xx and c=xxx 此語句可以用到索引
  • where b=xx and a=xx and c=xxx 同上,順序沒有關係,同樣能用到索引
  • where a=xx and b=xx 可以用到索引
  • where a=xx and c=xx 可以用到索引
  • where b=xx and c=xx 用不到索引
  • where b=xx 用不到索引
  • where c=xx 用不到索引

覆蓋索引

InnoDB存儲引擎支持覆蓋索引,即從輔助索引就可以得到查詢的記錄,而不需要查詢聚集索引中的記錄。使用覆蓋索引的好處是輔助索引不包含整行記錄的所有信息,故其大小要遠小於聚集索引,因此可以減小大量的IO操作。

對於InnoDb存儲引擎的輔助索引而言,由於其中包含了主鍵信息,因此其葉子節點放的數據為(primary key1, primary key2,..., key1, key2,...)。對於下麵的可以僅用一次輔助聯合索引來完成查詢。

  • SELECT key2 FROM table key1 = xxx;
  • SELECT primary key1, key2 FROM table WHERE key1 = xxx;
  • SELECT primary key1, primary key2, key2 FROM table WHERE key1 = xxx;

簡單的說,如果查詢的列,正好是我們設置的主鍵或者鍵(建立聚合索引的鍵),如上圖展示的,輔助索引的葉子節點的值就是所要查詢的內容,就不必取到鍵值後再去聚合索引進行二次查找。可以想到如果想要更多的使用覆蓋索引這一特性,需要將我們需要的列,都建立聯合索引。

聯合索引和覆蓋索引有很大的區別:

覆蓋索引是查詢的列可以直接通過索引提取,比如只查詢主鍵的列!或者查詢聯合索引的所有列或者左邊開始的部分列(註意有順序的)!

而聯合索引並不一定只從索引中能獲取到所有的數據,這個取決於你所查詢的列。比如select * from table where ××××××;的方式就不太可能是覆蓋索引。因此如果你查詢的列能用到聯合索引,且你查詢的列都能通過聯合索引獲取,比如你只查詢聯合索引所在的列或者左邊開始的部分列,這就相當於覆蓋索引了。通常為了讓查詢能用到覆蓋索引,就將要查詢的多列數據設置成聯合索引。

優化器不使用(輔助)索引的情況

在某些情況下,優化器並沒有選擇輔助索引去查找數據,而是通過掃描聚集索引,也就是直接進行全表的掃描來得到數據。

SELECT * FROM orderdetails WHERE orderid>10000 and orderid<102000;

通過SHOW INDEX FROM orderdetails可以看到可以使用的索引包括PRIMARY、OrderID、OrderOrder_Details三個索引,正常情況下,應該選擇OrderID輔助索引開始查詢,但是優化器直接選擇PRIMARY聚集索引。

原因在於我們要選取的數據是整行信息,而OrderID索引不能覆蓋到我們要查詢的信息(覆蓋索引),因此在對OrderID索引進行查詢到指定數據的操作後,還需要進行一次書簽訪問來查找整行信息。雖然在輔助索引中數據是順序存放的,但是再一次的書簽查找數據是無序的,因此變為了磁碟上的離散讀取操作。如果要訪問的數據量很小,那麼優化器還是會選擇輔助索引,但是當訪問的數據占整個表中數據的很大一部分時(一般是20%左右),優化器會選擇通過聚集索引來查找數據。

INDEX HINT

MYSQL資料庫支持INDEX HINT(索引提示),顯示的告訴優化器使用哪個索引,在以下情況下可能需要用到INDEX HINT:

  • MYSQL資料庫的優化器錯誤的選擇了某個索引,導致MYSQL語句運行很慢,情況少數。
  • 某SQL語句可以選擇的索引非常多,這時優化器選擇執行計劃時間的開銷就可能會大於SQL語言本身。通過INDEX HINT可以強制優化器使用某個索引,直接執行選擇指定的索引來完成索引。
USE INDEX

SELECT * FROM t USE INDEX(a) WHERE a=1 AND b=2;

使用USE INDEX可以告訴優化器可以選擇該索引,但是不是強制使用該索引。實際的使用優化器還是會根據自己的判斷進行選擇。

FORCE INDEX

SELECT * FROM t FORCE INDEX(a) WHERE a=1 AND b=2;

使用FORCE INDEX可以指定優化器選擇某個索引進行查詢。

T樹索引

對於MYSQL資料庫的NDB CLuster記憶體存儲引擎,在使用它時可將其視為記憶體資料庫。在記憶體資料庫中,一般使用T樹作為其索引的數據結構。T樹是有平衡二叉樹和B樹發展而來。T樹的好處是節點不存放數據,只存放指針,這樣能減少記憶體的使用,這對記憶體資料庫來說是很重要的。同時T樹也是一棵平衡二叉樹,以此保證查找的性能。

哈希索引

當前MYSQL資料庫中,Memory存儲引擎支持哈希索引。InnoDB存儲引擎支持自適應哈希索引,用戶僅能開啟該特性,不能對其進行人工干預。通過參數innodb_adaptive_hash_index來禁用或啟動此特性,預設為開啟。

轉載請註明出處。
作者:wuxiwei
出處:http://www.cnblogs.com/wxw16/p/6131132.html



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

-Advertisement-
Play Games
更多相關文章
  • 一、分析目的 為企業戰略決策、投資決策、營銷決策提供依據 二、分析思路 三、分析方法——廚藝大比拼 數據分析的過程 對比 分類 相關:相關分析研究的是事物間的某種聯繫,最常見的聯繫就是因果分析。 分佈:分佈分析就是集中和離散趨勢。 四、分析應用 巨集觀環境:PEST分析——政治(Political)環 ...
  • 我們在數據分析之前需要進行數據處理、數據錄入並把數據清洗乾凈,做好數據的加工和描述工作。 【參考文獻】《數據分析:企業的賢內助》 陳哲 著 ...
  • 統計某一特定網站的某個時辰訪客人數 所用版本:hadoop2.6.5 數據樣式如下: 輔助類 mapper 映射特定年份中每月每天每個時辰的訪客數 reducer 彙總一個時辰內訪客人數 driver 配置信息,程式入口 command result ...
  • 註: 出於職業要求, 本文中所有數字均被人為修改過, 並非真實數字, 很抱歉也不能貼出源代碼 目標: 個險客戶特征分析 背景: 目前市場部使用的推廣活動分析系統只能針對客戶調查返回的信息分析,且僅有年齡/性別/婚姻狀態/收入四個維度, 預測精度不高. 市場部希望能從現有的壽險客戶信息分析出影響他們選 ...
  • 當with和as一起用時,表示定義一個SQL字句 例: with sonword as ( select * from person ) select * from student where name in (select name from sonword) 相當於 select * from ...
  • mysql -u root -pvmware mysql>use mysql; mysql>update user set host = '%' where user = 'root'; mysql>flush privileges; mysql>select host, user from use ...
  • mongoDB中存儲的數據單元被稱作文檔。文檔的格式與JSON很類似,只不過由於JSON表達的數據類型範圍太小(null,boolean,numeric,string和object),mongoDB對其做了擴充,並命名為BSON。下麵對各個數據類型進行介紹。 null {‘x’: null},數據為... ...
  • 最近幫客戶實施的基於SQL Server AlwaysOn跨機房切換項目 最近一個來自重慶的客戶找到走起君,客戶的業務是做移動互聯網支付,是微信支付收單渠道合作伙伴,資料庫里存儲的是支付流水和交易流水。 由於客戶那邊沒有DBA,所以找到走起君商量一個資料庫伺服器搬遷項目。 項目背景 客戶需要把在10 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...