mysql組合索引與字段順序

不少時候,咱們在mysql中建立了索引,可是某些查詢仍是很慢,根本就沒有使用到索引!html

通常來講,多是某些字段沒有建立索引,或者是組合索引中字段的順序與查詢語句中字段的順序不符。mysql

看下面的例子:sql

假設有一張訂單表(orders),包含order_id和product_id二個字段。性能

一共有31條數據。符合下面語句的數據有5條。優化

執行下面的sql語句:ui

select product_id spa

from ordershtm

where order_id in (123, 312, 223, 132, 224);blog

這條語句要mysql去根據order_id進行搜索,而後返回匹配記錄中的product_id。索引

因此組合索引應該按照如下的順序建立:

create index orderid_productid on orders(order_id, product_id)

mysql> explain select product_id from orders where order_id in (123, 312, 223, 132, 224) \G

*************************** 1. row ***************************

           id: 1

  select_type: SIMPLE

        table: orders

         type: range

possible_keys: orderid_productid

          key: orderid_productid

      key_len: 5

          ref: NULL

         rows: 5

        Extra: Using where; Using index

1 row in set (0.00 sec)

能夠看到,這個組合索引被用到了,掃描的範圍也很小,只有5行。

若是把組合索引的順序換成product_id, order_id的話,

mysql就會去索引中搜索 *123 *312 *223 *132 *224,必然會有些慢了。

mysql> create index orderid_productid on orders(product_id, order_id);                                                       

Query OK, 31 rows affected (0.01 sec)

Records: 31  Duplicates: 0  Warnings: 0

mysql> explain select product_id from orders where order_id in (123, 312, 223, 132, 224) \G

*************************** 1. row ***************************

           id: 1

  select_type: SIMPLE

        table: orders

         type: index

possible_keys: NULL

          key: orderid_productid

      key_len: 10

          ref: NULL

         rows: 31

        Extra: Using where; Using index

1 row in set (0.00 sec)

此次索引搜索的性能顯然不能和上次相比了。

rows:31,個人表中一共就31條數據。

索引被使用部分的長度:key_len:10,比上一次的key_len:5多了一倍。

不知道是這樣在索引裏面查找速度快,仍是直接去全表掃描更快呢?

mysql> alter table orders add modify_a char(255) default 'aaa';

Query OK, 31 rows affected (0.01 sec)

Records: 31  Duplicates: 0  Warnings: 0

mysql> 

mysql> 

mysql> explain select modify_a from orders where order_id in (123, 312, 223, 132, 224) \G          

*************************** 1. row ***************************

           id: 1

  select_type: SIMPLE

        table: orders

         type: ALL

possible_keys: NULL

          key: NULL

      key_len: NULL

          ref: NULL

         rows: 31

        Extra: Using where

1 row in set (0.00 sec)

這樣就不會用到索引了。 剛纔是由於select的product_id與where中的order_id都在索引裏面的。

爲何要建立組合索引呢?這麼簡單的狀況直接建立一個order_id的索引不就好了嗎?

若是隻有一個order_id索引,沒什麼問題,會用到這個索引,而後mysql要去磁盤上的表裏面取到product_id。

若是有組合索引的話,mysql能夠徹底從索引中取到product_id,速度天然會快。

再多說幾句組合索引的最左優先原則:

組合索引的第一個字段必須出如今查詢組句中,這個索引纔會被用到。

若是有一個組合索引(col_a,col_b,col_c)

下面的狀況都會用到這個索引:

col_a = "some value";

col_a = "some value" and col_b = "some value";

col_a = "some value" and col_b = "some value" and col_c = "some value";

col_b = "some value" and col_a = "some value" and col_c = "some value";

對於最後一條語句,mysql會自動優化成第三條的樣子~~。

下面的狀況就不會用到索引:

col_b = "aaaaaa";

col_b = "aaaa" and col_c = "cccccc";


下列轉自:http://hi.baidu.com/liuzhiqun/blog/item/4957bcb1aed1b5590823023c.html

經過實例理解單列索引、多列索引以及最左前綴原則

實例:如今咱們想查出知足如下條件的用戶id:

mysql>SELECT `uid` FROM people WHERE lname`='Liu'  AND `fname`='Zhiqun' AND `age`=26

由於咱們不想掃描整表,故考慮用索引。

單列索引:

ALTER TABLE people ADD INDEX lname (lname);

將lname列建索引,這樣就把範圍限制在lname='Liu'的結果集1上,以後掃描結果集1,產生知足fname='Zhiqun'的結果集2,再掃描結果集2,找到 age=26的結果集3,即最終結果。

由 於創建了lname列的索引,與執行表的徹底掃描相比,效率提升了不少,但咱們要求掃描的記錄數量仍舊遠遠超過了實際所需 要的。雖然咱們能夠刪除lname列上的索引,再建立fname或者age 列的索引,可是,不論在哪一個列上建立索引搜索效率仍舊類似。

2.多列索引:

ALTER TABLE people ADD INDEX lname_fname_age (lame,fname,age);

爲了提升搜索效率,咱們須要考慮運用多列索引,因爲索引文件以B-Tree格式保存,因此咱們不用掃描任何記錄,便可獲得最終結果。

注:在mysql中執行查詢時,只能使用一個索引,若是咱們在lname,fname,age上分別建索引,執行查詢時,只能使用一個索引,mysql會選擇一個最嚴格(得到結果集記錄數最少)的索引。

3.最左前綴:顧名思義,就是最左優先,上例中咱們建立了lname_fname_age多列索引,至關於建立了(lname)單列索引,(lname,fname)組合索引以及(lname,fname,age)組合索引。

注:在建立多列索引時,要根據業務需求,where子句中使用最頻繁的一列放在最左邊。

相關文章
相關標籤/搜索