一、兩個一樣結構的語句一個沒有用到索引的問題:
查1到20號的就不用索引,查1到5號的就用索引,爲何呢?不穩定?
mysql> explain select * from test where f_submit_time between '2009-09-01' and '2009-09-20' \G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: test
type: ALL
possible_keys: PRIMARY,submit_time_index
key: NULL
key_len: NULL
ref: NULL
rows: 365628
Extra: Using where
1 row in set (0.02 sec)
mysql> explain select * from test where f_submit_time between '2009-09-01' and '2009-09-5' \G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: test
type: range
possible_keys: PRIMARY,submit_time_index
key: submit_time_index
key_len: 8
ref: NULL
rows: 52073
Extra: Using where
1 row in set (0.00 sec)
說明:
二叉樹索引原本最適合的就是點查詢,和小範圍的range查詢,
當預估返回的數據量超過必定比例( 貌似當預估的查詢量達到總量的30% )的時候,
再根據索引一條一條去查就慢了,反而不如全表掃描快了。Mysql有本身內部自動優化機制,
但有些自動優化機制可能不是最優的。這時候就須要人工去幹預。
好比長期不優化表,Mysql判斷出索引不優,就會不使用索引。
有時候就要人工強制使用真正高效的索引(FORCE INDEX)。
其實當自己的查詢就約等於一個全表查詢的時候,強不強制使用索引基本上沒什麼效果。mysql
二、再看個例子:
今天遇到一個奇怪的問題,明明已經創建了索引,select語句的explain也代表會利用這個索引,但是結果恰恰沒有用索引,最後掃描了全表。
兩個結構徹底同樣的sql語句:sql
sql1: select * from table where col_a = 123 and col_b in (‘foo’,\'bar’) order by id desc;
sql2: select * from table where col_a = 456 and col_b in (‘foo’,\'bar’) order by id desc;
結果sql1選擇利用了col_a的索引,速度很快,sql2利用了主鍵ID的索引,掃描了全表(40w行)。
仔細分析,發現數據庫中,col_a=456的記錄數有近1萬條,而col_a=123的記錄數只有幾條。
因而就清楚了,MySQL選擇索引不單單依據查詢結構和索引結構,還會根據索引大概估算選擇每種索引的數據量,而後選擇他認爲最快的索引。
多是主鍵索引會比普通index更快,因此mysql最後選擇了數據量跟大的id索引。
那麼,如何解決這個問題呢?
很簡單,只要在order語句裏寫多個鍵便可,好比:order by col_a, id desc數據庫
REF:mysql查詢中利用索引的機制 http://blogread.cn/it/article/5023?f=wb性能
三、本質緣由:Cardinality(索引基數)
很關鍵的一個參數,平均數值組=索引基數/表總數據行,平均數值組越接近1就越有可能利用索引。mysql索引
索引選擇性是不重複的索引值也叫基數(cardinality)表中數據行數的比值,索引選擇性=基數/數據行,基數能夠經過「show index from 表名」查看。
高索引選擇性的好處就是mysql查找匹配的時候能夠過濾更多的行,惟一索引的選擇性最佳,值爲1。優化
四、關於 mysql 索引優化與使用請見:
由淺入深探究mysql索引結構原理、性能分析與優化.net