MySql(五)之sql優化

##概述

作爲一個高級程序員,不僅要熟練使用sql語句,更應該使用高效的sql語句。

本篇blog講解的內容主要包括:

  1. 索引的使用。
  2. 執行計劃分析。
  3. sql優化常見案例分析。

##索引

一,什麼是索引

索引的作用只有一個,提高查找效率。

如下面sql語句:

select name from person where age = 16;

在正常情況下,MySql是從第一條數依次遍歷,直到讀完整個表才能得到所有age等於16的數據。

如果對age字段建立索引,MySql會維護一個索引表,索引表中存儲不同age與數據對對應關係,當查找age等於16的數據時會先在索引表中找到age等於16對應的數據id,然後直接根據數據id從數據表中需要的數據。這就類似於新華字典中的拼音查字法,先從拼音序列中找出這個字在哪一頁,然後直接去那一頁去找,避免翻遍整個字典,很大的提供了查找效率。

 

二,索引的利弊分析

上面說到創建索引會很大的提高查找效率,但索引也有弊端。

創建索引系統會自動維護一個索引表,每當數據增加,更新,刪除時都需要更改索引表,所以創建索引會降低增加,更新,刪除的效率。

三,創建索引的原則

創建索引針對的對象是字段,所以我們要找出適合創建索引的字段。

建議創建索引的列:

  1. 定義主鍵的數據列一定要建立索引。
  2. 定義有外鍵的數據列一定要建立索引。
  3. 對於經常查詢的數據列最好建立索引。
  4. 對於需要在指定範圍內的快速或頻繁查詢的數據列最好創建索引;
  5. 經常用在WHERE句中的數據列最好創建索引。
  6. 經常出現在關鍵字order by、group by、distinct後面的字段,建立索引。如果建立的是複合索引,索引的字段順序要和這些關鍵字後面的字段順序一致,否則索引不會被使用。

不建議創建索引的列:

  1. 對於那些查詢中很少涉及的列,重複值比較多的列不要建立索引。
  2. 對於定義爲text、image和bit的數據類型的列不要建立索引。
  3. 對於經常存取的列避免建立索引 
  4. 限制表上的索引數目。對一個存在大量更新操作的表,所建索引的數目一般不要超過3個,最多不要超過5個。索引雖說提高了訪問速度,但太多索引會影響數據的更新操作。
  5. 對複合索引,按照字段在查詢條件中出現的頻度建立索引。在複合索引中,記錄首先按照第一個字段排序。對於在第一個字段上取值相同的記錄,系統再按照第二個字段的取值排序,以此類推。因此只有複合索引的第一個字段出現在查詢條件中,該索引纔可能被使用,因此將應用頻度高的字段,放置在複合索引的前面,會使系統最大可能地使用此索引,發揮索引的作用。

注:具體怎麼哪些列可以創建索引,哪些列不建議創建索引,需要具體情況具體分析,需要開發中慢慢積累經驗。

四,創建索引

索引分爲單索引和組合索引。但索引是給一個字段創建的索引,組合索引是給多個字段創建的索引。

比如給person表中的age字段創建索引的sql是:

ALTER TABLE `xia`.`person` ADD INDEX(`age`) USING BTREE COMMENT '給age創建索引';

navicate也支持創建索引的圖形化操作,如下:

 

##執行計劃

執行計劃就是分析執行某個sql語句的詳細細節。

查看某個sql語句的執行計劃很容易,只有在sql語句前添加EXPLAIN關鍵詞即可。如下:

EXPLAIN select  * from person WHERE age = 16 and id > 0;

執行結果如下:

說明:

  1. type:表示執行sql使用了哪種類型。類型的種類從好到差依次是:const、eq_reg、ref、range、indexhe和ALL。
  2. possible_keys:可能使用到的索引。此時有兩個:PRIMARY,index_age。其中PRIMARY是主鍵,index_age是自己創建的索引。
  3. key:實際用到的索引。
  4. key_len:使用索引的長度,該值越小越好。
  5. ref:
  6. rows:數據遍歷的行數,數值越小越好。

總結:要學會且有意識的多使用執行計劃,查看每一個sql語句的執行計劃,儘量優化sql,提高項目的執行效率。

 

##sql優化具體分析

sql優化主要針對查詢sql進行優化,因爲只有查詢語句纔會出現掃描全表的情況。隨着數據量的增大,掃描全表會非常耗時,優化sql的目的是儘量掃描少的數據量。

具體細節如下:

1,儘量給字段設置默認值,避免字段值爲null情況。

如果字段是int類型的age,首先給age創建索引時null不會參與創建索引。where age=0比where age is null效率高。

 

2,在where語句中少使用or,使用or將不使用索引。

如select name where age = 16 or age = 20

可以寫成:

select name where age = 16 union all select name where age = 20

 

3,在where語句中避免使用in,

如select * from score where student_id in (select id from student where name='guoxiang')

可以寫成:

select * from score sc  where exists (select 1 from student st  where st.name='guoxiang' and st.id = sc.student_id)

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章