mysql索引:
MyISAM引擎使用B+Tree作爲索引結構,和DB2的索引一樣,葉節點的data域存放的是數據記錄的地址,
InnoDB的引擎的cluster index葉子節點存放的就是數據本身,如果表沒有primary key或者unique key,
那麼InnoDB默認會以隱藏字段DB_ROW_ID作爲key創建cluster index,二級索引的葉子節點則存放的是
主鍵的值.
問題:cluster index的主要目的是數據頁的物理和索引鍵的順序一致,這樣在獲取一組範圍的數據的時候
可以讀取連續數據頁減少I/O和數據頁數.InnoDB默認以DB_ROW_ID創建cluster index或者人爲創建自增
字段作爲主鍵,這樣可以連續插入數據頁,是可以避免insert或者update等寫性能影響,可是這樣的主鍵
又不是常用被搜索鍵值,所以這樣的cluster index的好處是什麼呢?使用二級索引的時候,豈不是要進行
二次索引搜索?
瞭解索引幫助分析explain輸出,參考官方文檔:
https://dev.mysql.com/doc/refman/5.7/en/explain-output.html
EXPLAIN Join Types:幾種常見類型由好到差:
const,system-> ref->range->index->All
測試:create table t(a int primary key,b int,c int);
insert into t2 values(1,11,111),(2,22,222),(5,56,565),(9,32,322),(7,23,233);
create index bidx on t(b);
1.const:一行符合條件而且使用主鍵
mysql> explain select * from t where a=2\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t
partitions: NULL
type: const
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: const
rows: 1
filtered: 100.00
Extra: NULL
1 row in set, 1 warning (0.00 sec)
2.ref:ref官方解釋和例子:
All rows with matching index values are read from this table for each combination
of rows from the previous tables. ref is used if the join uses only a leftmost prefix
of the key or if the key is not a PRIMARY KEY or UNIQUE index (in other words, if
the join cannot select a single row based on the key value). If the key that is used
matches only a few rows, this is a good join type
SELECT * FROM ref_table WHERE key_column=expr;
SELECT * FROM ref_table,other_table
WHERE ref_table.key_column=other_table.column;
SELECT * FROM ref_table,other_table
WHERE ref_table.key_column_part1=other_table.column
AND ref_table.key_column_part2=1;
這裏測試使用非主鍵或非唯一鍵,返回匹配某個單獨值的所有行,也是ref:
mysql> explain select * from t where b=22\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t
partitions: NULL
type: ref
possible_keys: bidx
key: bidx
key_len: 5
ref: const
rows: 1
filtered: 100.00
Extra: NULL
1 row in set, 1 warning (0.00 sec)
如果把*改成a,b,extra就變成了using index,就是覆蓋索引,即所有值都可以從索引中獲得:
mysql> explain select a,b from t where b=22\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t
partitions: NULL
type: ref
possible_keys: bidx
key: bidx
key_len: 5
ref: const
rows: 1
filtered: 100.00
Extra: Using index
1 row in set, 1 warning (0.00 sec)
3.rang:使用索引讀取了一定範圍的數據Only rows that are in a given range are retrieved, using an index to select the rows.
The key column in the output row indicates which index is used. The key_len contains
the longest key part that was used. The ref column is NULL for this type.
mysql> explain select * from t where a>3 \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t
partitions: NULL
type: range
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: NULL
rows: 3
filtered: 100.00
Extra: Using where
1 row in set, 1 warning (0.00 sec)
4.index:SQL語句只訪問索引列
mysql> explain select a,b from t \G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t
partitions: NULL
type: index
possible_keys: NULL
key: bidx
key_len: 5
ref: NULL
rows: 5
filtered: 100.00
Extra: Using index
1 row in set, 1 warning (0.00 sec)
5.All:全表掃描
sql> explain select * from t where c=222\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t
partitions: NULL
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 5
filtered: 20.00
Extra: Using where
1 row in set, 1 warning (0.00 sec)
6.刪除原來bidx索引,在b,c列創建聯合索引create index bcidx on t(b,c);
排序時候可以使用索引:
mysql> explain select * from t where b=11 order by c\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t
partitions: NULL
type: ref
possible_keys: bcidx
key: bcidx
key_len: 5
ref: const
rows: 3
filtered: 100.00
Extra: Using where; Using index
1 row in set, 1 warning (0.00 sec)
把聯合索引b改爲範圍查找,索引b後面的字段失效,排序無法使用索引:
mysql> explain select * from t where b>11 order by c\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t
partitions: NULL
type: range
possible_keys: bcidx
key: bcidx
key_len: 5
ref: NULL
rows: 4
filtered: 100.00
Extra: Using where; Using index; Using filesort
1 row in set, 1 warning (0.00 sec)
排序順序和索引順序不一樣,排序也無法使用索引:
mysql> explain select * from t order by b desc,c\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t
partitions: NULL
type: index
possible_keys: NULL
key: bcidx
key_len: 10
ref: NULL
rows: 7
filtered: 100.00
Extra: Using index; Using filesort
1 row in set, 1 warning (0.00 sec)