【mysql】索引的優化

寫在前面的話html

查詢容易,優化不易,且寫且珍惜mysql

mysql結構

從MySQL邏輯架構來看,MySQL有三層架構,第一層鏈接,第二層查詢解析、分析、優化、視圖、緩存,第三層,存儲引擎算法

 

MySQL有哪些索引類型 ?

從數據結構角度sql

一、B+樹索引(O(log(n))):關於B+樹索引,能夠參考 MySQL索引背後的數據結構及算法原理segmentfault

二、hash索引:
a 僅僅能知足"=","IN"和"<=>"查詢,不能使用範圍查詢
b 其檢索效率很是高,索引的檢索能夠一次定位,不像B-Tree 索引須要從根節點到枝節點,最後才能訪問到頁節點這樣屢次的IO訪問,因此 Hash 索引的查詢效率要遠高於 B-Tree 索引
c 只有Memory存儲引擎顯示支持hash索引緩存

三、FULLTEXT索引(如今MyISAM和InnoDB引擎都支持了)數據結構

四、R-Tree索引(用於對GIS數據類型建立SPATIAL索引)架構

從物理存儲角度函數

一、彙集索引(clustered index)工具

二、非彙集索引(non-clustered index)

從邏輯角度

一、主鍵索引:主鍵索引是一種特殊的惟一索引,不容許有空值

二、普通索引或者單列索引

三、多列索引(複合索引):複合索引指多個字段上建立的索引,只有在查詢條件中使用了建立索引時的第一個字段,索引纔會被使用。使用複合索引時遵循最左前綴集合

四、惟一索引或者非惟一索引

五、空間索引:空間索引是對空間數據類型的字段創建的索引,MYSQL中的空間數據類型有4種,分別是GEOMETRY、POINT、LINESTRING、POLYGON。
MYSQL使用SPATIAL關鍵字進行擴展,使得可以用於建立正規索引類型的語法建立空間索引。建立空間索引的列,必須將其聲明爲NOT NULL,空間索引只能在存儲引擎爲MYISAM的表中建立

CREATE TABLE table_name[col_name data type]
[unique|fulltext|spatial][index|key][index_name](col_name[length])[asc|desc]

一、unique|fulltext|spatial爲可選參數,分別表示惟一索引、全文索引和空間索引;
二、index和key爲同義詞,二者做用相同,用來指定建立索引
三、col_name爲須要建立索引的字段列,該列必須從數據表中該定義的多個列中選擇;
四、index_name指定索引的名稱,爲可選參數,若是不指定,MYSQL默認col_name爲索引值;
五、length爲可選參數,表示索引的長度,只有字符串類型的字段才能指定索引長度;
六、asc或desc指定升序或降序的索引值存儲

創建索引的原則

一、基數很低的字段不建立索引,更新很是頻繁的字段不適合建立索引

二、MySQL不支持bitmap索引

三、採用第三方系統實現 Text/Blob 的全文索引(Sphinx、Coreseek、Lucene、ElashSearch)

四、經常使用的 where、ORDER BY 、GROUP BY 、DISTINCT 字段要創建索引

五、索引不能太多,會有負做用

六、多使用聯合索引、少使用獨立索引

七、字符型可建立前綴索引(如 username 字段 80% 的數據都小於18個字符,那麼能夠建立18個字符的前綴索引

八、字段的順序對組合索引效率有相當重要的做用,過濾效果越好的字段須要更靠前

最左前綴匹配原則,很是重要的原則,mysql會一直向右匹配直到遇到範圍查詢(>、<、between、like)就中止匹配,好比a = 1 and b = 2 and c > 3 and d = 4 若是創建(a,b,c,d)順序的索引,d是用不到索引的,若是創建(a,b,d,c)的索引則均可以用到,a,b,d的順序能夠任意調整儘可能的擴展索引,不要新建索引。好比表中已經有a的索引,如今要加(a,b)的索引,那麼只須要修改原來的索引便可=和in能夠亂序,好比a = 1 and b = 2 and c = 3 創建(a,b,c)索引能夠任意順序,mysql的查詢優化器會幫你優化成索引能夠識別的形式

九、MySQL只對如下操做符才使用索引

  • <,<=,=,>,>=,between,
  • 某些時候的like(不以通配符%或_開頭的情形)
  • 若已對名爲col_name的列建了索引,則形如"col_name is null"的SQL會用到索引
  • 若sql語句中的where條件不僅1個條件,則MySQL會進行Index Merge優化來縮小候選集範圍

十、不要過分索引,只保持所需的索引。每一個額外的索引都要佔用額外的磁盤空間,並下降寫操做的性能。 在修改表的內容時,索引必須進行更新,有時可能須要重構,所以,索引越多,所花的時間越長。

沒法使用索引的場景

一、經過索引掃描的記錄數超過30%會進行全表掃描

二、第一個索引列使用範圍查詢不能使用索引

三、內存表使用Hash進行全表掃描

四、ORDER BY 、GROUP BY Hash索引只能進行等於/不等於的檢索

五、SELECT … WHERE key1 = ? ORDER BY key2 ASC 對於key1和key2上的索引,查詢優化器會本身判斷用哪一個(只能用到一個)

六、表關聯字段類型要同樣(包括長度),不然會有類型轉換

七、使用函數時不能用到索引( WHERE func(key1) = ? 不能用到)( WHERE key1 + 1 = ? 不能用到)(WHERE key1 = ? + ? 能夠用到)

索引有哪些「反作用」

一、增,刪,改都須要修訂索引,索引存在額外的維護成本

二、查找翻閱索引系統須要消耗時間,索引存在額外的訪問成本

三、索引系統須要一個地方來存放,索引存在額外的空間成本

 

索引工具

mysqlidxchx/pt-index-usage/userstat/check-unused-keys

一、mysqlidxchx工具很長時間沒有更新,但主要用來分析general log、slow.log,來判斷實例中那個索引是能夠刪除,但這個工具沒有通過實戰,風險很大。

二、pt-index-usage原理來相似mysqlidxchx,執行過程當中性能消耗比較嚴重,若是要在生產庫上部署,最好在凌晨業務低鋒時使用,pt-index-usage只支持slow.log格式的文件,若是要全面分析整個實例索引使用狀況,須要long_query_time設置成0,才能把因此的sql記錄下來,但同時會對磁盤空間形成壓力,同時pt-index-usage對大文件分析就是件痛苦的事。固然pt-index-usage能夠考慮部分表索引使用狀況的確認。

三、最看好的userstat,收集信息性能優越,成本低。這個patch是google貢獻的(userstat_running),percona把它更名成userstat,默認是不開啓的,開啓是會收集客戶端、索引、表、線程信息存儲在CLIENT_STATISTICS、INDEX_STATISTICS、TABLE_STATISTICS、THREAD_STATISTICS。Userstat的bug致使的問題太嚴重,直接致使mysql crash,到目前淘寶生產環境尚未使用。

四、Ryan Lowe的check-unused-keys腳本基於userstat,可以比較方便輸出須要刪除的索引。

參考地址

http://www.mysqlperformanceblog.com/2012/06/30/find-unused-indexes/http://www.mysqlperformanceblog.com/2012/12/05/quickly-finding-unused-indexes-and-estimating-their-size/http://www.mysqlperformanceblog.com/2009/06/26/check-unused-keys-a-tool-to-interact-with-index_statistics/

相關文章
相關標籤/搜索