利用 index、explain和profile最佳化mysql資料庫查詢小結

來源:互聯網
上載者:User

想必大家對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

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.