我們后臺開發(fā)人員每天都難免與數(shù)據(jù)庫打交道,那么你在寫sql語句的時候有注重到自己sql的效率嗎伶选?當你sql查詢速度很慢的時候你有想過是你的sql語句造成的嗎深员?看完這篇文章嗓违,我相信你會對sql優(yōu)化有了一定的了解入宦!
explain
通過查看sql執(zhí)行計劃來確定各部位的問題哺徊。使用方法:在sql語句前面加上explain關鍵字。
explain SELECT * FROM (SELECT id FROM sys_address where remarks='中國' or remarks='中國重慶' or remarks='中國重慶重慶市' or remarks like '%渝北區(qū)%') a
執(zhí)行結(jié)果:
id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extr |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | SIMPLE | sys_address | ALL | 667651 | 35.2 | Using where |
參數(shù)說明:
- id
id值越大乾闰,優(yōu)先級越高落追,就越先執(zhí)行。如果id值一樣涯肩,那可以看成一組轿钠。
- select_type
常見的值以及含義:
SIMPLE 簡單的select查詢,查詢中不包含子查詢或者UNION病苗。
PRIMARY 查詢中若包含任何復雜的子部分疗垛,最外層查詢則被標記為PRIMARY。
SUBQUERY 在SELECT或WHERE列表中包含了子查詢硫朦。
DERIVED 在FROM列表中包含的子查詢被標記為DERIVED(衍生)贷腕,MySQL會遞歸執(zhí)行這些子查詢,把結(jié)果放在臨時表中阵幸。
UNION 若第二個SELECT出現(xiàn)在UNION之后,則被標記為UNION:若UNION包含在FROM子句的子查詢中芽世,外層SELECT將被標記為:DERIVED挚赊。
UNION RESULT 從UNION表獲取結(jié)果的SELECT。
- table
值就是當前執(zhí)行的表名济瓢。
partitions
type
**執(zhí)行效率 **system > const > eq_ref > ref > range > index > all
system:表僅有一行(=系統(tǒng)表)荠割。這是const聯(lián)接類型的一個特例。
const:表最多有一個匹配行旺矾,它將在查詢開始時被讀取蔑鹦。因為僅有一行,在這行的列值可被優(yōu)化器剩余部分認為是常數(shù)箕宙。
const用于用常數(shù)值比較PRIMARY KEY或UNIQUE索引的所有部分時嚎朽。
eq_ref:對于每個來自于前面的表的行組合,從該表中讀取一行柬帕。這可能是最好的聯(lián)接類型哟忍,除了const類型狡门。它用在一個索引
的所有部分被聯(lián)接使用并且索引是UNIQUE或PRIMARY KEY。eq_ref可以用于使用= 操作符比較的帶索引的列锅很。比較值可以為常量或
一個使用在該表前面所讀取的表的列的表達式其馏。
ref:對于每個來自于前面的表的行組合,所有有匹配索引值的行將從這張表中讀取爆安。如果聯(lián)接只使用鍵的最左邊的前綴叛复,或如
果鍵不是UNIQUE或PRIMARY KEY(換句話說,如果聯(lián)接不能基于關鍵字選擇單個行的話)扔仓,則使用ref褐奥。如果使用的鍵僅僅匹配少量
行,該聯(lián)接類型是不錯的当辐。ref可以用于使用=或<=>操作符的帶索引的列抖僵。
ref_or_null:該聯(lián)接類型如同ref,但是添加了MySQL可以專門搜索包含NULL值的行缘揪。在解決子查詢中經(jīng)常使用該聯(lián)接類型的
優(yōu)化耍群。
index_merge:該聯(lián)接類型表示使用了索引合并優(yōu)化方法。在這種情況下找筝,key列包含了使用的索引的清單蹈垢,key_len包含了使
用的索引的最長的關鍵元素。
unique_subquery:該類型替換了下面形式的IN子查詢的ref:value IN (SELECT primary_key FROMsingle_table WHERE
some_expr);unique_subquery是一個索引查找函數(shù)袖裕,可以完全替換子查詢曹抬,效率更高。
index_subquery:該聯(lián)接類型類似于unique_subquery急鳄“瘢可以替換IN子查詢,但只適合下列形式的子查詢中的非唯一索引:
value IN (SELECT key_column FROM single_table WHERE some_expr)
range:只檢索給定范圍的行疾宏,使用一個索引來選擇行张足。key列顯示使用了哪個索引。key_len包含所使用索引的最長關鍵元素坎藐。
在該類型中ref列為NULL为牍。當使用=、<>岩馍、>碉咆、>=、<蛀恩、<=疫铜、IS NULL、<=>双谆、BETWEEN或者IN操作符块攒,用常量比較關鍵字列時励稳,
可以使用range。
- possible_keys
possible_keys列指出MySQL能使用哪個索引在該表中找到行囱井。注意驹尼,該列完全獨立于EXPLAIN輸出所示的表的次序。這意味著
在possible_keys中的某些鍵實際上不能按生成的表次序使用庞呕。
- key
key列顯示MySQL實際決定使用的鍵(索引)新翎。如果沒有選擇索引,鍵是NULL住练。要想強制MySQL使用或忽視possible_keys列中的
索引地啰,在查詢中使用FORCE INDEX、USE INDEX或者IGNORE INDEX讲逛。
- key_len
key_len列顯示MySQL決定使用的鍵長度亏吝。如果鍵是NULL,則長度為NULL盏混。注意通過key_len值我們可以確定MySQL將實際使
用一個多部關鍵字的幾個部分蔚鸥。
- ref
ref列顯示使用哪個列或常數(shù)與key一起從表中選擇行。
- rows
rows列顯示MySQL認為它執(zhí)行查詢時必須檢查的行數(shù)许赃。
filtered
Extr
該列包含MySQL解決查詢的詳細信息止喷。
Distinct:MySQL發(fā)現(xiàn)第1個匹配行后,停止為當前的行組合搜索更多的行混聊。
Not exists:MySQL能夠?qū)Σ樵冞M行LEFT JOIN優(yōu)化弹谁,發(fā)現(xiàn)1個匹配LEFT JOIN標準的行后,不再為前面的的行組合在該表內(nèi)檢
查更多的行句喜。
range checked for each record (index map: #):MySQL沒有發(fā)現(xiàn)好的可以使用的索引预愤,但發(fā)現(xiàn)如果來自前面的表的列值已
知,可能部分索引可以使用咳胃。對前面的表的每個行組合植康,MySQL檢查是否可以使用range或index_merge訪問方法來索取行。
Using filesort:MySQL需要額外的一次傳遞拙绊,以找出如何按排序順序檢索行向图。通過根據(jù)聯(lián)接類型瀏覽所有行并為所有匹配
WHERE子句的行保存排序關鍵字和行的指針來完成排序泳秀。然后關鍵字被排序标沪,并按排序順序檢索行。
Using index:從只使用索引樹中的信息而不需要進一步搜索讀取實際的行來檢索表中的列信息嗜傅。當查詢只使用作為單一索引一
部分的列時金句,可以使用該策略。
Using temporary:為了解決查詢吕嘀,MySQL需要創(chuàng)建一個臨時表來容納結(jié)果违寞。典型情況如查詢包含可以按不同情況列出列的
GROUP BY和ORDER BY子句時贞瞒。
Using where:WHERE子句用于限制哪一個行匹配下一個表或發(fā)送到客戶。除非你專門從表中索取或檢查所有行趁曼,如果Extra值
不為Using where并且表聯(lián)接類型為ALL或index军浆,查詢可能會有一些錯誤。
Using sort_union(...), Using union(...), Using intersect(...):這些函數(shù)說明如何為index_merge聯(lián)接類型合并索引掃描挡闰。
Using index for group-by:類似于訪問表的Using index方式乒融,Using index for group-by表示MySQL發(fā)現(xiàn)了一個索引,可
以用來查詢GROUP BY或DISTINCT查詢的所有列摄悯,而不要額外搜索硬盤訪問實際的表赞季。并且,按最有效的方式使用索引奢驯,以便對于
每個組申钩,只讀取少量索引條目。
索引
索引的作用就是加快查詢速度瘪阁,它就像書的目錄撒遣,當你想獲取到里面內(nèi)容位置時,就需要可以通過目錄快速的定位到具體位置罗洗。
首先我們需要明確一點愉舔,索引并不是越多越好。因為寫入數(shù)據(jù)時伙菜,會對索引字段進行一些處理轩缤,就會影響插入速度。
在MySql中的常用索引:
- 主鍵索引
一個表中只有一個主鍵索引贩绕,一般在建表的時候就自動存在了火的。由系統(tǒng)自動創(chuàng)建,不需要額外手動創(chuàng)建淑倾。
- 普通索引
一般索引馏鹤。
ALTER TABLE table_name ADD INDEX 索引名(column1,column2);
- 唯一索引
表示列中不能有重復值。
ALTER TABLE `table_name` ADD UNIQUE (`column`)娇哆;
- 全文索引
通常用于文本值中湃累,比如商品詳細信息等。
合理添加索引
查詢頻繁的字段碍讨,應該添加索引治力。
更新頻繁的字段,不應該添加索引勃黍。
唯一性太差的字段不應該添加索引宵统,比如sex性別字段。
索引失效
以下幾種情況覆获,即使字段創(chuàng)建了索引马澈,也不會使用到瓢省。
like語句以“%”開頭。
or語句的字段沒有全部使用索引痊班,其中任意一個沒有索引的話勤婚,此條件就不會使用索引。
在組合查詢中涤伐,第一個查詢字段的名稱不是復合索引中的第一列蛔六。
在索引列上使用IS NULL 或者IS NOT NULL,索引是不能索引空值的废亭,這樣的操作會導致全表掃描国章。
在索引字段上使用not 、<>豆村、!=液兽。
在索引字段上執(zhí)行函數(shù),如DATE_FORMAT(data, format)掌动。