mysql 索引- 笔记
索引
? ?mysql最常用的索引結構是btree(O(log(n))),但是總有一些情況下我們為了更好的性能希望能使用別的類型的索引。hash就是其中一種選擇,例如我們在通過用戶名檢索用戶id的時候,他們總是一對一的關系,用到的操作符只是=而已,假如使用hash作為索引數據結構的話,時間復雜度可以降到O(1)。不幸的是,目前的mysql版本(5.6)中,hash只支持MEMORY和NDB兩種引擎,而我們最常用的INNODB和MYISAM都不支持hash類型的索引。
1、BTree索引:
BTree(多路搜索樹,并不是二叉的)是一種常見的數據結構。使用BTree結構可以顯著減少定位記錄時所經歷的中間過程,從而加快存取速度。按照翻譯,B 通常認為是Balance的簡稱。這個數據結構一般用于數據庫的索引,綜合效率較高。
B-Tree索引可以被用在像=,>,>=,<,<=和BETWEEN這些比較操作符上。而且還可以用于LIKE操作符,只要它的查詢條件是一個不以通配符開頭的常量。
EXPLAIN select * from blog.my_user where `name` in ('rhythmk251','rhythmk2151','rhythmk7251','rhythmk685'); +----+-------------+---------+------+---------------+------+---------+------+--------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+---------+------+---------------+------+---------+------+--------+-------------+ | 1 | SIMPLE | my_user | ALL | NULL | NULL | NULL | NULL | 778424 | Using where | +----+-------------+---------+------+---------------+------+---------+------+--------+-------------+ 1 row in set
添加 idx_name 索引:
ALTER TABLE blog.`my_user` ADD INDEX `idx_name` (`name`) USING BTREE ;mysql> EXPLAIN select * from blog.my_user where `name` in ('rhythmk251','rhythmk2151','rhythmk7251','rhythmk685'); +----+-------------+---------+-------+---------------+----------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+---------+-------+---------------+----------+---------+------+------+-------------+ | 1 | SIMPLE | my_user | range | idx_name | idx_name | 303 | NULL | 4 | Using where | +----+-------------+---------+-------+---------------+----------+---------+------+------+-------------+mysql> EXPLAIN select * from blog.my_user where `name` LIKE 'rhythmk830%'; +----+-------------+---------+-------+---------------+----------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+---------+-------+---------------+----------+---------+------+------+-------------+ | 1 | SIMPLE | my_user | range | idx_name | idx_name | 303 | NULL | 11 | Using where | +----+-------------+---------+-------+---------------+----------+---------+------+------+-------------+ 1 row in set任何一個沒有覆蓋所有WHERE中AND級別條件的索引是不會被使用的。也就是說,要使用一個索引,這個索引中的第一列需要在每個AND組中出現。
mysql> EXPLAIN select * from blog.my_user where `name` LIKE 'rhythmk830%' or age>35; +----+-------------+---------+------+---------------+------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+---------+------+---------------+------+---------+------+------+-------------+ | 1 | SIMPLE | my_user | ALL | idx_name | NULL | NULL | NULL | 7266 | Using where | +----+-------------+---------+------+---------------+------+---------+------+------+-------------+ 1 row in set mysql> EXPLAIN select * from blog.my_user where `name` LIKE 'rhythmk830%' and age>35; +----+-------------+---------+-------+---------------+----------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+---------+-------+---------------+----------+---------+------+------+-------------+ | 1 | SIMPLE | my_user | range | idx_name | idx_name | 303 | NULL | 11 | Using where | +----+-------------+---------+-------+---------------+----------+---------+------+------+-------------+ 1 row in set有時候mysql不會使用索引,即使這個在可用的情況下。例如當mysql預估使用索引會讀取大部分的行數據時。(在這種情況下,一次全表掃描可能比使用索引更快,因為它需要更少的檢索)。然而,假如語句中使用LIMIT來限定返回的行數,mysql則會使用索引。因為當結果行數較少的情況下使用索引的效率會更高。
mysql> EXPLAIN select * from blog.my_user where `name` <> 'rhythmk830' ; +----+-------------+---------+------+---------------+------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+---------+------+---------------+------+---------+------+------+-------------+ | 1 | SIMPLE | my_user | ALL | idx_name | NULL | NULL | NULL | 7769 | Using where | +----+-------------+---------+------+---------------+------+---------+------+------+-------------+ 1 row in setmysql> EXPLAIN select * from blog.my_user where `name` <> 'rhythmk830' limit 5; +----+-------------+---------+-------+---------------+----------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+---------+-------+---------------+----------+---------+------+------+-------------+ | 1 | SIMPLE | my_user | range | idx_name | idx_name | 303 | NULL | 5658 | Using where | +----+-------------+---------+-------+---------------+----------+---------+------+------+-------------+ 1 row in set2、Hash 索引特征:
Hash類型的索引有一些區別于以上所述的特征:
精確查找非常快(包括= <> 和in),其檢索效率非常高,索引的檢索可以一次定位,不像BTree 索引需要從根節點到枝節點,所以 Hash 索引的查詢效率要遠高于 B-Tree 索引。
不適合:
1、不適合模糊查詢和范圍查詢(包括like,>,<,between……and等)。由于 Hash 索引比較的是進行 Hash 運算之后的 Hash 值,所以它只能用于等值的過濾,不能用于基于范圍的過濾,因為經過相應的 Hash 算法處理之后的 Hash 值的大小關系,并不能保證和Hash運算前完全一樣;
2、不適合排序,數據庫無法利用索引的數據來提升排序性能,同樣是因為Hash值的大小不確定;
3、復合索引不能利用部分索引字段查詢,Hash 索引在計算 Hash 值的時候是組合索引鍵合并后再一起計算 Hash 值,而不是單獨計算 Hash 值,所以通過組合索引的前面一個或幾個索引鍵進行查詢的時候,Hash 索引也無法被利用。
3、備注:
1、索引列需要根據業務判斷 ,在where條件中出現的列。
2、使用索引需要考慮某列中值的分布,比如性別,搜索 “男/女” 都會得出大約一半的行,所有索引沒有多大的用處。
3、使用短索引好處多多。對字符串進行索引的時候,應該指定一個前綴長度。索引長度小,節約索引空間及磁盤IO同時讓索引,短的值比較起來更快,同時Mysql 可以在內存中存儲更多的值。
4、利用最左前綴。創建一個多列索引,可起幾個索引的作用。因為可利用索引最左邊的列來匹配行。這樣的列集稱為最左前綴。
5、不要過度索引。 額外的索引需要占用空間,并降低寫操作的性能。修改表的時候索引必須進行更新,有時可能需要重構,索引越多時間越長。索引太多,也可能導致MYSQL選擇不到最優索引。
6、INNODB 存儲引擎,記錄優先按主鍵保存,如果沒有主鍵,但是有唯一索引那么就按唯一索引列保存。如果兩者都沒有,那么表中會生成一個內部列。按照這個列的順序保存,InnoDB普通索引都會保存主鍵,所以主鍵要盡可能選擇較短的數據類型。
?7、盡量避免NULL:應該指定列為NOT NULL,除非你想存儲NULL。在MySQL中,含有空值的列很難進行查詢優化,因為它們使得索引、索引的統計信息以及比較運算更加復雜。你應該用0、一個特殊的值或者一個空串代替空值。
?8、使用--查看當前session所有已產生的profile??
? ? ??
轉載于:https://www.cnblogs.com/rhythmK/p/5352714.html
總結
以上是生活随笔為你收集整理的mysql 索引- 笔记的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 配置mysql使其允许外部ip进行登录
- 下一篇: MySQL分区管理