注意:Index(Name,Age)表示在Name,Age兩列上創建聯合索引
因爲索引對數據庫的查詢性能有着相當重要的影響,下面是個人一些總結和體會:
一個查詢一次只能使用一個索引:select name from user where name='plantegg' and age>35 , 若是Index(name); Index(age)的話,MySQL查詢優化器會自動選擇一個索引來使用;
MySQL選擇哪一個索引,能夠這樣來看:mysql> show index from photo;
+-------+------------+------------------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-------+------------+------------------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+
| photo | 0 | PRIMARY | 1 | photo_id | A | 237871 | NULL | NULL | | BTREE | |
| photo | 1 | index_random | 1 | random | A | 237871 | NULL | NULL | YES | BTREE | |
| photo | 1 | FK_photo_profile_id | 1 | profile_id | A | 237871 | NULL | NULL | | BTREE | |
| photo | 1 | FK_photo_temp_photo_id | 1 | temp_photo_id | A | 237871 | NULL | NULL | YES | BTREE | |
| photo | 1 | FK_photo_album_id | 1 | album_id | A | 237871 | NULL | NULL | YES | BTREE | |
+-------+------------+------------------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+
Cardinality越大表示索引候選分得越細(默認都是BTree索引);
你也能夠試試Force Index強制使用某個索引看看速度是否是MySQL是否是查詢起來更快(若是真是這樣的話你須要Analyze yourTable 了,MySQL從新計算你的Cardinality以幫助他正確地選擇INDEX)
仔細分析Explain的結果:重點留意Extra,Key,Rows,Select_type的結果!
當心查詢中的Group by 、order by之類的,基本上這樣的查詢在Explain的時候都會出現: Using where; Using temporary; Using filesort
聯 合索引要當心使用,Index(Name,Age)時,若是where name='pp' 能使用索引,where age=25時不能使用索引;where name='pp' and age>25 能使用索引; where name ='pp' order by age 能使用索引; where name>'pp' order by age 不能使用索引,可是 where name>'pp' order by name,age 能使用索引,請仔細留意差別 ; order by name asc age desc 將不能使用索引!
索引只有被加入到內存裏的時候對你的查詢纔有幫助,若是索引太大根本沒法放入內存這樣的索引失去了意義!訪問索引的時候還須要Random Aceess Disk這比不用索引還慢!
select 的 時候能不用select * 就不要用,也就是須要哪些列只拿那些列(Hibernate那些對性能沒有啥好處的),好比:在Index(Name)的時候,select * from user where name like 'pp%' 和 select name from user where name like 'pp%' 二者性能千差萬別,若是有10000條符合記錄的結果的話(User表總共有10億條記錄)前一個查詢可能須要2分鐘(假設你的系統每秒100 IOPS的樣子)後一個查詢可能只須要0.01秒!由於前一個查詢要從硬盤上取出散佈在處處的這10000條記錄,後一個查詢直接從內存中的索引上拿 Name就夠了!後一個查詢你explain的時候在Extra中會看到Using Index。
永遠要警戒對磁盤的隨機訪問,順序讀寫 和隨機訪問的性能差異是N個數量級的(順序讀寫的時候你的OS、Dish Cache 這個時候大顯身手)對這個問題若是感興趣的話建議你去用C寫個測試程序,隨機讀寫的時候不斷地fseek,相應地一樣的功能你不要fseek而是經過順序 讀寫到內存中,在內存本身扔掉那些應該由磁盤去fseek的地方,應該明白個人意思吧!
5.0.27後,MYSQL就支持set profling=1了,這樣能夠詳細分析你的SQL語句每一步驟的時間消耗了
若是order by 的時候有 limit + 索引配合的話,你會有意外驚喜的。