部份內容轉自:http://www.2cto.com/database/201211/172380.htmlhtml
比較好的文章:http://www.cnblogs.com/hustcat/archive/2009/10/28/1591648.htmlmysql
MyISAM算法
MyISAM引擎使用B+Tree做爲索引結構,葉節點的data域存放的是數據記錄的地址。下圖是MyISAM索引的原理圖:sql
這裏設表一共有三列,假設咱們以Col1爲主鍵,則上圖是一個MyISAM表的主索引(Primary key)示意。能夠看出MyISAM的索引文件僅僅保存數據記錄的地址。在MyISAM中,主索引和輔助索引(Secondary key)在結構上沒有任何區別,只是主索引要求key是惟一的,而輔助索引的key能夠重複。若是咱們在Col2上創建一個輔助索引,則此索引的結構以下圖所示:優化
mysql> show create table t2; +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Table | Create Table | +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | t2 | CREATE TABLE `t2` ( `column_a` int(11) DEFAULT NULL, `column_b` int(11) DEFAULT NULL, `column_c` int(11) DEFAULT NULL, `column_d` varchar(10) DEFAULT NULL, KEY `index_a_b_c` (`column_a`,`column_b`,`column_c`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 | +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec) mysql> show index from t2 \G *************************** 1. row *************************** Table: t2 Non_unique: 1 Key_name: index_a_b_c Seq_in_index: 1 Column_name: column_a Collation: A Cardinality: 9 Sub_part: NULL Packed: NULL Null: YES Index_type: BTREE Comment: Index_comment: *************************** 2. row *************************** Table: t2 Non_unique: 1 Key_name: index_a_b_c Seq_in_index: 2 Column_name: column_b Collation: A Cardinality: 9 Sub_part: NULL Packed: NULL Null: YES Index_type: BTREE Comment: Index_comment: *************************** 3. row *************************** Table: t2 Non_unique: 1 Key_name: index_a_b_c Seq_in_index: 3 Column_name: column_c Collation: A Cardinality: 9 Sub_part: NULL Packed: NULL Null: YES Index_type: BTREE Comment: Index_comment: 3 rows in set (0.00 sec) mysql> select count(*) from t2; +----------+ | count(*) | +----------+ | 9 | +----------+ 1 row in set (0.01 sec)
show index語法的說明:spa
1、Table:索引所在的表名。 2、Non_unique:非惟一的索引,能夠看到primary key是0,由於必須是惟一的。 3、Key_name:索引的名稱,我們能夠經過這個名稱來drop index。 4、Seq_in_index:索引中該列的位置,若是看聯合索引就比較直觀。(例如上面例子) 5、Column_name:索引的列。 6、Collation:列以什麼方式存儲在索引中。能夠是‘A’或者NULL。B+樹索引老是A,即排序的。若是使用了Heap存儲索引,而且創建了Hash索引,這裏就會顯示NULL。由於Hash根據Hash桶來存放索引數據,而不是對數據進行排序。 7、Cardinality:很是關鍵的值,表示索引中惟一值得數目的估計值,優化器會根據這個值來判斷查詢是否使用這個索引。Cardinality/表的行數的比值應儘量接近1,若是很是小,那麼須要考慮是否還須要建這個索引。這個值不是實時更新的,由於開銷會很大,能夠經過運行ANALYZE TABLE或myisamchk -a能夠更新這個值。 8、Sub_part:是不是列的部分被索引。假設若是看index_a這個索引,這裏顯示10,表示只索引a列的前10個字符。若是索引整個列,則該字段爲NULL。 9、Packed:關鍵字如何被壓縮。若是沒有被壓縮,則爲NULL。 10、Null:是否索引的列含有NULL值。能夠看到index_a_b_c這裏爲YES,由於咱們定義的a、b、c列容許NULL值。 11、Index_type:索引的類型。InnoDB存儲引擎只支持B+樹索引,因此這裏顯示的都是BTREE。 12、Comment:註釋。
聯合索引形象的說明能夠比喻成手機中的電話薄,由於聯合索引是多個鍵值的B+樹狀況,和單列索引的鍵值順序排序相同,使用聯合索引也是經過葉節點邏輯上的順序地讀出全部數據,好比表中column1和column2要建一個index_1_2,那這個聯合索引會先按照column1順序存放,在column1值相同的數據,再使用coiumn2順序存放。例如:(1,1),(1,2),(2,1),(2,4),(3,1),(3,2),按照(column1,column2)的順序進行存放:3d
mysql> explain select * from t2 where column_a=1 and column_b=2 and column_c=3; +----+-------------+-------+------+---------------+-------------+---------+-------------------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+-------------+---------+-------------------+------+-------------+ | 1 | SIMPLE | t2 | ref | index_a_b_c | index_a_b_c | 15 | const,const,const | 1 | Using where | +----+-------------+-------+------+---------------+-------------+---------+-------------------+------+-------------+ 1 row in set (0.00 sec) mysql> explain select * from t2 where column_a=1 and column_b=2; +----+-------------+-------+------+---------------+-------------+---------+-------------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+-------------+---------+-------------+------+-------------+ | 1 | SIMPLE | t2 | ref | index_a_b_c | index_a_b_c | 10 | const,const | 1 | Using where | +----+-------------+-------+------+---------------+-------------+---------+-------------+------+-------------+ 1 row in set (0.00 sec) mysql> explain select * from t2 where column_a=1; +----+-------------+-------+------+---------------+-------------+---------+-------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+-------------+---------+-------+------+-------------+ | 1 | SIMPLE | t2 | ref | index_a_b_c | index_a_b_c | 5 | const | 1 | Using where | +----+-------------+-------+------+---------------+-------------+---------+-------+------+-------------+ 1 row in set (0.00 sec)
另外針對column_a和column_c兩列的查詢,實際上只是用到了組合索引中的column_a部分:code
mysql> explain select * from t2 where column_a=1 and column_c=3; +----+-------------+-------+------+---------------+-------------+---------+-------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+-------------+---------+-------+------+-------------+ | 1 | SIMPLE | t2 | ref | index_a_b_c | index_a_b_c | 5 | const | 2 | Using where | +----+-------------+-------+------+---------------+-------------+---------+-------+------+-------------+ 1 row in set (0.00 sec)
能夠看到key_len是5,查詢經過索引index_a_b_c的column_a中找到相應column_a=1行的葉子節點邏輯位置區域,可是因爲條件column_c沒法被使用到索引,遍歷了column_a=1的全部行。htm
因此你們習慣說的聯合索引的"最左前綴"的原則,簡單的理解就是隻從聯合索引組合的最左側的列開始的組合順序組合。blog
理解了聯合索引機制,什麼用不到就更好理解:
mysql> explain select * from t2 where column_b=2 and column_c=3; +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ | 1 | SIMPLE | t2 | ALL | NULL | NULL | NULL | NULL | 9 | Using where | +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ 1 row in set (0.00 sec) mysql> explain select * from t2 where column_b=2; +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ | 1 | SIMPLE | t2 | ALL | NULL | NULL | NULL | NULL | 9 | Using where | +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ 1 row in set (0.00 sec) mysql> explain select * from t2 where column_c=3; +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ | 1 | SIMPLE | t2 | ALL | NULL | NULL | NULL | NULL | 9 | Using where | +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ 1 row in set (0.00 sec)