本文的重點在於如何構建乙個高效能的mysql索引,從中你可以學到如何分析乙個索引是不是好索引,以及如何構建乙個好的索引。
乙個索引的常見誤區是為每一列建立乙個索引,如下面建立的索引:
create table `t` (
`c1` varchar(
50
) default null,
`c2` varchar(
50
) default null,
`c3` varchar(
50
) default null,
key `c1` (`c1`),
key `c2` (`c2`),
key `c3` (`c3`)
) engine=innodb default charset=utf8;
t表裡有三列,並且為每列建立了乙個索引。建立索引的人為了能夠快速訪問表中的任何一列,因此為每一列新增了乙個單獨的索引。在多個列上建立索引通常並不能很好的提高mysql查詢效能,雖然說mysql 5.0之後引入了索引合併策略,可以將多個單列索引合併成乙個索引,但這並不總是有效的。同時建立多個索引的時候還會增加資料插入的成本,在插入資料的時候需要同時維護多個索引的寫入操作。
看下面這條sql語句:
select name from student where id +
1
=
5
即使我們在student表的id列上建立索引,上面的這條sql語句也無法使用索引。sql語句中索引字段不能是表示式的一部分,也不能是函式的引數。
建立索引另外乙個需要考慮的是索引的選擇性,通常情況下我們會使用選擇性高的列作為索引,但是也不一定一直是這樣,下一節會介紹如何權衡索引的選擇性。
在選擇索引的順序的時候有乙個原則:將索引選擇性最高的列放在左側,同時索引的順序要與查詢索引的順序一致,並且要兼顧考慮排序和分組的需要。在乙個多列b樹多列中索引的順序意味著索引首先按照最左側的列進行排序,其次是第二列。所以無論是where語句還是order by語句都需要盡量滿足這個順序,這樣才能更好的使用索引。
列的選擇性高的含義是通過這一列能夠更多的過濾掉無用的資料,舉個極端的例子,如果把自增id建成索引那麼它的選擇性是最高的,因為會把無用的資料都過濾掉,只會剩下一條有效資料。我們可以通過下面的方式來簡單衡量某乙個列的選擇性:
select count(distinct columna)/count(*) as selectivity from table
當上面的資料越大的時候意味著columna的選擇性越高。這種方式提供了乙個衡量平均選擇性的辦法,但是也不一定是有效的,需要具體情況具體分析。
當遇到特別長的列,但又必須要建立索引的時候可以考慮建立字首索引。字首索引的含義是把某一列的前n個字元作為索引,建立字首索引的方式如下:
alter table test add key(columna(
5
));
上面這個語句就是把columna的前5個字元建立為字首索引。字首索引是一種使索引更小、更快的有效辦法。但是字首所有有乙個缺點:mysql無法使用字首索引來做order by和group by,也無法使用字首索引做覆蓋掃瞄。
聚簇索引代表一種資料的儲存方式,表示同乙個結構中儲存了b-tree索引和資料行。也就是說當建立聚簇索引的時候實際的資料行存放在索引的葉子節點上。這也決定了每個表只能有乙個聚簇索引。
聚簇索引組織資料的方式如下圖所示:
從圖中可以看到索引的葉子節點和資料行是存放在一起的,這樣的好處是可以直接讀取到資料行。在建立表的時候如果我們不顯式指定聚簇索引,那麼mysql將會按照下面的邏輯來選擇聚簇索引:首先會通過主鍵列來聚集資料,如果沒有主鍵列那麼會選擇唯一的非空索引來替代。如果還沒有這樣的索引那麼會隱式的建立乙個主鍵列來作為聚簇索引。
聚簇索引優點:
1、相關資料存放在一起,檢索的時候降低io的次數
2、資料訪問更快
3、使用覆蓋索引掃瞄的查詢可以直接使用節點中的主鍵值
在使用上面的優點的時候聚簇索引也有一定的缺點:
1、聚簇索引將資料聚集在一起限制了插入速度,插入速度比較依賴於主鍵的順序
2、更新索引的時候代價會變高
3、二級索引的訪問的時候需要查詢兩次
非聚簇索引通常被稱為二級索引,與聚簇索引的不同在於,非聚簇索引的葉子節點存放的是資料的行指標或者是乙個主鍵值。這樣在查詢資料的時候首先定位到葉子節點上的主鍵值(或者行指標),然後通過主鍵值再到聚簇索引中查詢到對應的資料。從中我們可以看到對於非聚簇索引的查詢需要走兩次索引。下圖是乙個非聚簇索引:
這個索引是innodb中的耳機索引,葉子節點中儲存的是索引和主鍵。對於myisam葉子節點儲存的是索引和行指標。
如果乙個索引包含或者說覆蓋所有需要查詢的字段的值,那麼就稱為覆蓋索引。覆蓋索引可以極大的提高查詢的效率,如果我們的查詢中只查詢索引,而不用去回表那應該最好不過了。
通常我們使用explain關鍵字來檢視乙個查詢語句的執行計畫,通過執行計畫我們可以了解到查詢的細節。如果是覆蓋索引,我們會看到執行計畫的extra列裡有」using index」的資訊。在查詢語句中一般我們希望是where條件中的語句盡量能被覆蓋,並且順序要跟索引的保持一致。還有乙個需要注意的點是mysql不能在索引中使用like操作,這樣會導致後面的索引失效。
那如何學習才能快速入門並精通呢?
當真正開始學習的時候難免不知道從哪入手,導致效率低下影響繼續學習的信心。
加架構qq群:681065582,免費領取以上學習資料
如何構建高效能MySQL索引
本文的重點在於如何構建乙個高效能的mysql索引,從中你可以學到如何分析乙個索引是不是好索引,以及如何構建乙個好的索引。乙個索引的常見誤區是為每一列建立乙個索引,如下面建立的索引 t表裡有三列,並且為每列建立了乙個索引。建立索引的人為了能夠快速訪問表中的任何一列,因此為每一列新增了乙個單獨的索引。在...
如何構建高效能MySQL索引
乙個索引的常見誤區是為每一列建立乙個索引,如下面建立的索引 create table t c1 varchar 50 default null,c2 varchar 50 default null,c3 varchar 50 default null,key c1 c1 key c2 c2 key ...
mysql高效能索引 mysql高效能索引( )
在開發中,我們知道大多數應用的瓶頸在於sql語句的執行時耗,在這裡並不討論sql語句的安全,僅僅討論高效能sql語句,而與高效能sql語句緊密相連的就是傳說中的 索引。索引 一種工作在儲存引擎端的用於快速找到記錄的一種資料結構。mysql使用索引的方式是 先找到索引的值,再根據索引的值找到資料行。索...