大多數MySQL存儲引擎默認使用的是B+樹的索引,不同的存儲引擎用不同的方式使用B+樹索引,MyISAM使用前綴壓縮技術使得索引更小,但是InnoDB則按照元數據格式進行存儲;MyISAM索引通過數據的物理位置引用被索引的行,而InnoDB則根據主鍵引用被索引的行。
B樹 和 B+ 樹
B樹:
B+樹:
區(qū)別:
為什么說 B+樹比 B-樹更適合實際應用中操作系統(tǒng)的文件索引和數據庫索引?
為什么不用紅黑樹?
哈希索引基于哈希表實現,對于每一行數據,存儲引擎會對所有的索引列計算一個哈希碼,通過哈希碼能以 O(1) 時間進行查找,但是無法用于排序與分組,并且只支持精確查找,無法用于部分查找和范圍查找。
在MySQL 中,只有Memory引擎顯式支持哈希索引
InnoDB 存儲引擎有一個特殊的功能叫“自適應哈希索引”,當某個索引值被使用的非常頻繁時,會在 B+Tree 索引之上再創(chuàng)建一個哈希索引,這樣就讓 B+Tree 索引具有哈希索引的一些優(yōu)點,比如快速的哈希查找。
MyISAM 存儲引擎支持空間數據索引(R-Tree),可以用于地理數據存儲。空間數據索引會從所有維度來索引數據,可以有效地使用任意維度來進行組合查詢。
必須使用 GIS 相關的函數來維護數據。
MyISAM 存儲引擎支持全文索引,用于查找文本中的關鍵詞,而不是直接比較是否相等。
查找條件使用 MATCH AGAINST,而不是普通的 WHERE。全文索引使用倒排索引實現,它記錄著關鍵詞到其所在文檔的映射。
InnoDB 存儲引擎在 MySQL 5.6.4 版本中也開始支持全文索引。
優(yōu)點
缺點
如果MySQL查詢的列不是獨立的,就不會使用索引,“獨立的列”指的是,索引列不能是表達式的一部分,也不能是函數的參數
例如
mysql> SELECT id, name FROM t_user WHERE id + 1 = 5;
MySQL無法解析這個 id + 1 方程式,我們應該養(yǎng)成簡化WHERE條件的習慣
有時候需要索引很長的字符列,這會讓索引變得大且慢
比如對于 BLOB、TEXT 和 VARCHAR 類型的列,必須使用前綴索引,只索引開始的部分字符。
前綴長度的選取需要根據索引選擇性來確定
很多人對于多列索引的理解都不夠,一個常見的錯誤就是,為每個列創(chuàng)建獨立的索引,或者按照錯誤的順序創(chuàng)建多列索引
在多個列上建立獨立的單列索引大部分情況下并不能提高MySQL的查詢性能,所以引入“索引合并”的策略,一定程度上可以使用表上的多個單列索引來定位指定的行。
例如下面的語句中,最好把 username 和 password 設置為多列索引。
SELECT username, password FROM t_user WHERE username = 'Aiguodala' AND password = 'Aiguodala';
讓選擇性最強的索引列放在前面。
索引的選擇性是指:不重復的索引值和記錄總數的比值。最大值為 1,此時每個記錄都有唯一的索引與其對應。選擇性越高,每個記錄的區(qū)分度越高,查詢效率也越高。
聚簇索引并不是一種單獨的索引類型,而是一種數據存儲方式,術語“聚簇”表示數據行和相鄰的鍵值緊湊地存儲在一起。
InnoDB 通過主鍵聚集數據,如果沒有定義主鍵,InnoDB會選擇一個唯一的非空索引來代替,如果沒有這樣的索引,InnoDB會隱式的定義一個主鍵來作為聚簇索引。
聚集的數據的優(yōu)缺點
優(yōu)點:
缺點:
非聚簇索引
將數據存儲于索引分開結構,索引結構的葉子節(jié)點指向了數據的對應行,myisam通過key_buffer把索引先緩存到內存中,當需要訪問數據時(通過索引訪問數據),在內存中直接搜索索引,然后通過索引找到磁盤相應數據,這也就是為什么索引不在key buffer命中時,速度慢的原因
索引覆蓋所有需要查詢的字段的值
好處:
使用 EXPLAIN 關鍵字可以模擬優(yōu)化器執(zhí)行 SQL 查詢語句,從而知道 MySQL 是如何處理你的 SQL 語句的。分析你的查詢語句或是表結構的性能瓶頸
舉例:
id是select查詢的序列號,包含一組數字,表示查詢中執(zhí)行select子句或操作表的順序
id相同:執(zhí)行順序為 從上至下執(zhí)行
EXPLAIN SELECT * FROM t1, t2, t3 WHERE t1.id = t2.id AND t2.id = t3.id;
id不同:執(zhí)行順序為 id大的先執(zhí)行
EXPLAIN SELECT t2.id FROM t2 WHERE t2.id = (SELECT t1.id FROM t1 WHERE t1.id = (SELECT t3.id FROM t3) );
select_type代表查詢的類型,主要是用于區(qū)別普通查詢、聯(lián)合查詢、子查詢等的復雜查詢
select_type 屬性 | 含義 |
---|---|
SIMPLE | 簡單的 select 查詢,查詢中不包含子查詢或者 UNION |
PRIMARY | 查詢中若包含任何復雜的子部分,最外層查詢則被標記為 Primary |
DERIVED | 在 FROM 列表中包含的子查詢被標記為 DERIVED(衍生) MySQL 會遞歸執(zhí)行這些子查詢, 把結果放在臨時表里 |
SUBQUERY | 在SELECT或WHERE列表中包含了子查詢,WHERE 后面是單個值(=) |
DEPEDENT SUBQUERY | 在SELECT或WHERE列表中包含了子查詢,子查詢基于外層,WHERE 后面是一組值(IN) |
UNCACHEABLE SUBQUERY | 無法使用緩存的子查詢 |
UNION | 若第二個SELECT出現在UNION之后,則被標記為UNION; 若UNION包含在FROM子句的子查詢中,外層SELECT將被標記為:DERIVED |
UNION RESULT | 從UNION表獲取結果的SELECT |
table表示這個數據是基于哪張表的
type 是查詢的訪問類型。是較為重要的一個指標,結果值從最好到最壞依次是:
system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > all --常見的順序為 system > const > eq_ref > ref > range > index > all
一般來說,得保證查詢至少達到 range 級別,最好能達到 ref
類型名 | 含義 |
---|---|
SYSTEM | 表只有一行記錄(等于系統(tǒng)表),這是 const 類型的特列,平時不會出現,這個也可以忽略不計 |
CONST | 表示通過索引一次就找到了,const 用于比較 primary key 或者 unique 索引。因為只匹配一行數據,所以很快。如將主鍵置于 where 列表中,MySQL 就能將該查詢轉換為一個常量 |
EQ_REF | 唯一性索引掃描,對于每個索引鍵,表中只有一條記錄與之匹配。常見于主鍵或唯一索引掃描 |
REF | 非唯一性索引掃描,返回匹配某個單獨值的所有行。本質上也是一種索引訪問,它返回所有匹配某個單獨值的行, 然而,它可能會找到多個符合條件的行,所以他應該屬于查找和掃描的混合體 |
RANGE | 只檢索給定范圍的行,使用一個索引來選擇行。key 列顯示使用了哪個索引一般就是在你的 where 語句中出現 了 between、、>、in 等的查詢這種范圍掃描索引掃描比全表掃描要好,因為它只需要開始于索引的某一點,而 結束語另一點,不用掃描全部索引 |
INDEX | 出現index是sql使用了索引但是沒用通過索引進行過濾,一般是使用了覆蓋索引或者是利用索引進行了排序分組 |
ALL | Full Table Scan,將遍歷全表以找到匹配的行 |
顯示可能應用在這張表中的索引,一個或多個。查詢涉及到的字段上若存在索引,則該索引將被列出,但不一 定被查詢實際使用
實際使用的索引。如果為NULL,則沒有使用索引
表示索引中使用的字節(jié)數,可通過該列計算查詢中使用的索引的長度。 key_len 字段能夠幫你檢查是否充分的利用上了索引
ken_len 越長,說明索引使用的越充分
ref顯示索引的哪一列被使用了,如果可能的話,可以是一個常數。哪些列或常量被用于查找索引列上的值
rows 列顯示 MySQL 認為它執(zhí)行查詢時必須檢查的行數。越少越好!
其他的額外重要的信息
到此這篇關于MySQL創(chuàng)建高性能索引的文章就介紹到這了,更多相關MySQL高性能索引內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!