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