利用 index、explain和profile優化mysql數據庫查詢小結


想必大家對index,explain和profile的利用也很多,這是我最近兩天優化mysql語句查詢資料整理的一些內容,希望大家可以一起來補充一下。

index的使用:

1.最好是在相同類型的字段間進行比較的操作。在MySQL 3.23版之前,這甚至是一個必須的條件。例如不能將一個建有索引的INT字段和BIGINT字段進行比較;但是作為特殊的情況,在CHAR類型的字段和VARCHAR類型字段的字段大小相同的時候,可以將它們進行比較。

2.在建有索引的字段上盡量不要使用函數進行操作,盡量不要在數據庫中做運算。 

3.避免負向查詢和%前綴模糊查詢,like 'xxx%'百分號后綴查詢可以在此字段上使用索引。   

4.不要在生產環境程序中使用select * from 的形式查詢數據。只查詢需要使用的列。  

5.查詢盡可能使用limit減少返回的行數,減少數據傳輸時間和帶寬浪費。  

6.對查詢列使用函數用不到索引。  

7.避免隱式類型轉換,例如字符型一定要用’’,數字型一定不要使用’’。  

8.所有的SQL關鍵詞用大寫,養成良好的習慣,避免SQL語句重復編譯造成系統資源的浪費。  

9.聯表查詢的時候,記得把小結果集放在前面,遵循小結構及驅動大結果集的原則,這條很重要!  

10.開啟慢查詢,定期用explain優化慢查詢中的SQL語句。

11.任何對列的操作都將導致表掃描,它包括數據庫函數、計算表達式等等,查詢時要盡可能將操作移至等號右邊。

12.IN、OR子句常會使用工作表,使索引失效。如果不產生大量重復值,可以考慮把子句拆開。拆開的子句中應該包含索引。

13.索引不會包含有NULL值的列,只要列中包含有NULL值都將不會被包含在索引中,復合索引中只要有一列含有NULL值,那么這一列對於此復合索引就是無效的。所以我們在數據庫設計時不要讓字段的默認值為NULL。 

14.使用短索引,對串列進行索引,如果可能應該指定一個前綴長度。例如,如果有一個CHAR(255)的 列,如果在前10 個或20 個字符內,多數值是惟一的,那么就不要對整個列進行索引。短索引不僅可以提高查詢速度而且可以節省磁盤空間和I/O操作。

15.排序的索引問題,mysql查詢只使用一個索引,因此如果where子句中已經使用了索引的話,那么order by中的列是不會使用索引的。因此數據庫默認排序可以符合要求的情況下不要使用排序操作;盡量不要包含多個列的排序,如果需要最好給這些列創建復合索引。 

 

什么情況下應不建或少建索引

1.表記錄太少

如果一個表只有5條記錄,采用索引去訪問記錄的話,那首先需訪問索引表,再通過索引表訪問數據表,一般索引表與數據表不在同一個數據塊,這種情況下ORACLE至少要往返讀取數據塊兩次。而不用索引的情況下ORACLE會將所有的數據一次讀出,處理速度顯然會比用索引快。   如表zl_sybm(使用部門)一般只有幾條記錄,除了主關鍵字外對任何一個字段建索引都不會產生性能優化,實際上如果對這個表進行了統計分析后ORACLE也不會用你建的索引,而是自動執行全表訪問。如:   select * from zl_sybm where sydw_bh=’5401’(對sydw_bh建立索引不會產生性能優化)   經常插入、刪除、修改的表

對一些經常處理的業務表應在查詢允許的情況下盡量減少索引,如zl_yhbm,gc_dfss,gc_dfys,gc_fpdy等業務表。  

 

2.數據重復且分布平均的表字段

假如一個表有10萬行記錄,有一個字段A只有T和F兩種值,且每個值的分布概率大約為50%,那么對這種表A字段建索引一般不會提高數據庫的查詢速度。   經常和主字段一塊查詢但主字段索引值比較多的表字段如 gc_dfss(電費實收)表經常按收費序號、戶標識編號、抄表日期、電費發生年月、操作 標志來具體查詢某一筆收款的情況,如果將所有的字段都建在一個索引里那將會增加數據的修改、插入、刪除時間,從實際上分析一筆收款如果按收費序號索引就已 經將記錄減少到只有幾條,如果再按后面的幾個字段索引查詢將對性能不產生太大的影響。   對千萬級MySQL數據庫建立索引的事項及提高性能的手段.

 

MySQL索引類型包括:

 

1.普通索引

這是最基本的索引,它沒有任何限制。它有以下幾種創建方式:

◆創建索引

CREATE INDEX indexName ON mytable(username(length)); 如果是CHAR,VARCHAR類型,length可以小於字段實際長度;如果是BLOB和TEXT類型,必須指定 length,下同。

◆修改表結構

ALTER mytable ADD INDEX [indexName] ON (username(length)) ◆創建表的時候直接指定

CREATE TABLE mytable(   ID INT NOT NULL,    username VARCHAR(16) NOT NULL,   INDEX [indexName] (username(length))   );  刪除索引的語法:

DROP INDEX [indexName] ON mytable;

 

2.唯一索引

它與前面的普通索引類似,不同的就是:索引列的值必須唯一,但允許有空值。如果是組合索引,則列值的組合必須唯一。它有以下幾種創建方式:

◆創建索引

CREATE UNIQUE INDEX indexName ON mytable(username(length)) ◆修改表結構

ALTER mytable ADD UNIQUE [indexName] ON (username(length)) ◆創建表的時候直接指定

CREATE TABLE mytable(   ID INT NOT NULL,    username VARCHAR(16) NOT NULL,   UNIQUE [indexName] (username(length))   ); 

 

3.主鍵索引

它是一種特殊的唯一索引,不允許有空值。一般是在建表的時候同時創建主鍵索引:

CREATE TABLE mytable(   ID INT NOT NULL,    username VARCHAR(16) NOT NULL,   PRIMARY KEY(ID)   );  當然也可以用 ALTER 命令。記住:一個表只能有一個主鍵。

4.組合索引

為了形象地對比單列索引和組合索引,為表添加多個字段:

CREATE TABLE mytable(   ID INT NOT NULL,    username VARCHAR(16) NOT NULL,   city VARCHAR(50) NOT NULL,   age INT NOT NULL  );  為了進一步榨取MySQL的效率,就要考慮建立組合索引。就是將 name, city, age建到一個索引里:

ALTER TABLE mytable ADD INDEX name_city_age (username(10),city,age); 建表時,usernname長度為 16,這里用 10。這是因為一般情況下名字的長度不會超過10,這樣會加速索引查詢速度,還會減少索引文件的大小,提高INSERT的更新速度。

如果分別在 usernname,city,age上建立單列索引,讓該表有3個單列索引,查詢時和上述的組合索引效率也會大不一樣,遠遠低於我們的組合索引。雖然此時有了三個索引,但MySQL只能用到其中的那個它認為似乎是最有效率的單列索引。

建立這樣的組合索引,其實是相當於分別建立了下面三組組合索引:

usernname,city,age   usernname,city   usernname  為什么沒有 city,age這樣的組合索引呢?這是因為MySQL組合索引“最左前綴”的結果。簡單的理解就是只從最左面的開始組合。並不是只要包含這三列的查詢都會用到該組合索引,下面的幾個SQL就會用到這個組合索引:

SELECT * FROM mytable WHREE username="admin" AND city="鄭州"  SELECT * FROM mytable WHREE username="admin" 而下面幾個則不會用到:

SELECT * FROM mytable WHREE age=20 AND city="鄭州"  SELECT * FROM mytable WHREE city="鄭州"

 

建立索引的時機

到這里我們已經學會了建立索引,那么我們需要在什么情況下建立索引呢?

一般來說,在WHERE和JOIN中出現的列需要建立索引,但也不完全如此,因為MySQL只對<,<=,=,>,>=,BETWEEN,IN,以及某些時候的LIKE才會使用索引。例如:

SELECT t.Name  FROM mytable t LEFT JOIN mytable m    ON t.Name=m.username WHERE m.age=20 AND m.city='鄭州' 此時就需要對city和age建立索引,由於mytable表的userame也出現在了JOIN子句中,也有對它建立索引的必要。

 

索引的不足之處

上面都在說使用索引的好處,但過多的使用索引將會造成濫用。因此索引也會有它的缺點:

1.雖然索引大大提高了查詢速度,同時卻會降低更新表的速度,如對表進行INSERT、UPDATE和DELETE。因為更新表時,MySQL不僅要保存數據,還要保存一下索引文件。

2.建立索引會占用磁盤空間的索引文件。一般情況這個問題不太嚴重,但如果你在一個大表上創建了多種組合索引,索引文件的會膨脹很快。

索引只是提高效率的一個因素,如果你的MySQL有大數據量的表,就需要花時間研究建立最優秀的索引,或優化查詢語句。

 

優化常用簡單操作:

set profiling = 1; 

expain (查詢語句);

show profiles;

show profile for query (查詢語句id);

create index aIndex on tablename(columnname);

根據explain檢測出mysql內部執行查詢的步驟和具體參數來優化自己的select語句。

 

(mysql研究的還不多,有很多需要補充和修正的地方,希望看了的兄弟姐妹們多多討論一下,共同學習,呵呵。。。)

 

轉載請注明出處:Edward_jie,http://www.cnblogs.com/promise-7/archive/2012/05/25/2517356.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM