萬盛學電腦網

 萬盛學電腦網 >> 數據庫 >> mysql教程 >> mysql索引優化方法 index

mysql索引優化方法 index

創建索引
對於查詢占主要的應用來說,索引顯得尤為重要。很多時候性能問題很簡單的就是因為我們忘了添加索引而造成的,或者說沒有添加更為有效的索引導致。如果不加
索引的話,那麼查找任何哪怕只是一條特定的數據都會進行一次全表掃描,如果一張表的數據量很大而符合條件的結果又很少,那麼不加索引會引起致命的性能下
降。但是也不是什麼情況都非得建索引不可,比如性別可能就只有兩個值,建索引不僅沒什麼優勢,還會影響到更新速度,這被稱為過度索引。
2,復合索引
比如有一條語句是這樣的:select * from users where area=’beijing’ and age=22;
如果我們是在area和age上分別創建單個索引的話,由於mysql查詢每次只能使用一個索引,所以雖然這樣已經相對不做索引時全表掃描提高了很多效
率,但是如果在area、age兩列上創建復合索引的話將帶來更高的效率。如果我們創建了(area, age,
salary)的復合索引,那麼其實相當於創建了(area,age,salary)、(area,age)、(area)三個索引,這被稱為最佳左前綴
特性。因此我們在創建復合索引時應該將最常用作限制條件的列放在最左邊,依次遞減。
3,索引不會包含有NULL值的列
只要列中包含有NULL值都將不會被包含在索引中,復合索引中只要有一列含有NULL值,那麼這一列對於此復合索引就是無效的。所以我們在數據庫設計時不要讓字段的默認值為NULL。
4,使用短索引
對串列進行索引,如果可能應該指定一個前綴長度。例如,如果有一個CHAR(255)的 列,如果在前10 個或20 個字符內,多數值是惟一的,那麼就不要對整個列進行索引。短索引不僅可以提高查詢速度而且可以節省磁盤空間和I/O操作。
5,排序的索引問題
mysql查詢只使用一個索引,因此如果where子句中已經使用了索引的話,那麼order by中的列是不會使用索引的。因此數據庫默認排序可以符合要求的情況下不要使用排序操作;盡量不要包含多個列的排序,如果需要最好給這些列創建復合索引。
6,like語句操作
一般情況下不鼓勵使用like操作,如果非使用不可,如何使用也是一個問題。like “%aaa%” 不會使用索引而like “aaa%”可以使用索引。
7,不要在列上進行運算
select * from users where
YEAR(adddate)
8,不使用NOT IN和操作
NOT IN和操作都不會使用索引將進行全表掃描。NOT IN可以NOT EXISTS代替,id3則可使用id>3 or id

ref_or_null

該聯接類型如同ref,但是添加了MySQL可以專門搜索包含NULL值的行。在解決子查詢中經常使用該聯接類型的優化。 在下面的例子中,MySQL可以使用ref_or_null聯接來處理ref_tables
SELECT * FROM ref_tableWHERE key_column=expr OR key_column IS NULL;
o        index_merge 該聯接類型表示使用了索引合並優化方法。在這種情況下,key列包含了使用的索引的清單,key_len包含了使用的索引的最長的關鍵元素。 o        unique_subquery 該類型替換了下面形式的IN子查詢的ref:
value IN (SELECT primary_key FROM single_table WHERE some_expr)
unique_subquery是一個索引查找函數,可以完全替換子查詢,效率更高。 o        index_subquery 該聯接類型類似於unique_subquery。可以替換IN子查詢,但只適合下列形式的子查詢中的非唯一索引:
value IN (SELECT key_column FROM single_table WHERE some_expr)
o        range 只檢索給定范圍的行,使用一個索引來選擇行。key列顯示使用了哪個索引。key_len包含所使用索引的最長關鍵元素。在該類型中ref列為NULL。 當使用=、<>、>、>=、<、<=、IS NULL、<=>、BETWEEN或者IN操作符,用常量比較關鍵字列時,可以使用range:
SELECT * FROM tbl_nameWHERE key_column = 10; 
SELECT * FROM tbl_nameWHERE key_column BETWEEN 10 and 20; 
SELECT * FROM tbl_nameWHERE key_column IN (10,20,30); 
SELECT * FROM tbl_nameWHERE key_part1= 10 AND key_part2 IN (10,20,30);
o        index 該聯接類型與ALL相同,除了只有索引樹被掃描。這通常比ALL快,因為索引文件通常比數據文件小。 當查詢只使用作為單索引一部分的列時,MySQL可以使用該聯接類型。 o        ALL 對於每個來自於先前的表的行組合,進行完整的表掃描。如果表是第一個沒標記const的表,這通常不好,並且通常在它情況下差。通常可以增加更多的索引而不要使用ALL,使得行能基於前面的表中的常數值或列值被檢索出。 ?         possible_keys possible_keys列指出MySQL能使用哪個索引在該表中找到行。注意,該列完全獨立於EXPLAIN輸出所示的表的次序。這意味著在possible_keys中的某些鍵實際上不能按生成的表次序使用。 如果該列是NULL,則沒有相關的索引。在這種情況下,可以通過檢查WHERE子句看是否它引用某些列或適合索引的列來提高你的查詢性能。如果是這樣,創造一個適當的索引並且再次用EXPLAIN檢查查詢。 為了看清一張表有什麼索引,使用SHOW INDEX FROM tbl_name。 ?         key key列顯示MySQL實際決定使用的鍵(索引)。如果沒有選擇索引,鍵是NULL。要想強制MySQL使用或忽視possible_keys列中的索引,在查詢中使用FORCE INDEX、USE INDEX或者IGNORE INDEX。 對於MyISAM和BDB表,運行ANALYZE TABLE可以幫助優化器選擇更好的索引。對於MyISAM表,可以使用myisamchk --analyze。 ?         key_len key_len列顯示MySQL決定使用的鍵長度。如果鍵是NULL,則長度為NULL。注意通過key_len值我們可以確定MySQL將實際使用一個多部關鍵字的幾個部分。 ?         ref ref列顯示使用哪個列或常數與key一起從表中選擇行。 ?         rows rows列顯示MySQL認為它執行查詢時必須檢查的行數。 ?         Extra 該列包含MySQL解決查詢的詳細信息。下面解釋了該列可以顯示的不同的文本字符串: o        Distinct MySQL發現第1個匹配行後,停止為當前的行組合搜索更多的行。 o        Not exists MySQL能夠對查詢進行LEFT JOIN優化,發現1個匹配LEFT JOIN標准的行後,不再為前面的的行組合在該表內檢查更多的行。 下面是一個可以這樣優化的查詢類型的例子: SELECT * 從t1 LEFT JOIN t2 ON t1.id=t2.id  WHERE t2.id IS NULL; 假定t2.id定義為NOT NULL。在這種情況下,MySQL使用t1.id的值掃描t1並查找t2中的行。如果MySQL在t2中發現一個匹配的行,它知道t2.id絕不會為NULL,並且不再掃描t2內有相同的id值的行。換句話說,對於t1的每個行,MySQL只需要在t2中查找一次,無論t2內實際有多少匹配的行。 o        range checked for each record (index map: #) MySQL沒有發現好的可以使用的索引,但發現如果來自前面的表的列值已知,可能部分索引可以使用。對前面的表的每個行組合,MySQL檢查是否可以使用range或index_merge訪問方法來索取行。 這並不很快,但比執行沒有索引的聯接要快得多。 o        Using filesort MySQL需要額外的一次傳遞,以找出如何按排序順序檢索行。通過根據聯接類型浏覽所有行並為所有匹配WHERE子句的行保存排序關鍵字和行的指針來完成排序。然後關鍵字被排序,並按排序順序檢索行。 o        Using index 從只使用索引樹中的信息而不需要進一步搜索讀取實際的行來檢索表中的列信息。當查詢只使用作為單一索引一部分的列時,可以使用該策略。 o        Using temporary 為了解決查詢,MySQL需要創建一個臨時表來容納結果。典型情況如查詢包含可以按不同情況列出列的GROUP BY和ORDER BY子句時。 o        Using where WHERE子句用於限制哪一個行匹配下一個表或發送到客戶。除非你專門從表中索取或檢查所有行,如果Extra值不為Using where並且表聯接類型為ALL或index,查詢可能會有一些錯誤。 如果想要使查詢盡可能快,應找出Using filesort 和Using temporary的Extra值。 o        Using sort_union(...), Using union(...), Using intersect(...) 這些函數說明如何為index_merge聯接類型合並索引掃描。 o        Using index for group-by 類似於訪問表的Using index方式,Using index for group-by表示MySQL發現了一個索引,可以用來查詢GROUP BY或DISTINCT查詢的所有列,而不要額外搜索硬盤訪問實際的表。並且,按最有效的方式使用索引,以便對於每個組,只讀取少量索引條目。 通過相乘EXPLAIN輸出的rows列的所有值,你能得到一個關於一個聯接如何的提示。這應該粗略地告訴你MySQL必須檢查多少行以執行查詢。當你使用max_join_size變量限制查詢時,也用這個乘積來確定執行哪個多表SELECT語句。
copyright © 萬盛學電腦網 all rights reserved