Mysql 索引優(yōu)化

聯(lián)合索引和單個(gè)索引選擇

## 一個(gè)字段不重復(fù)的總量與數(shù)據(jù)總量的比值,越大選擇性越好。

SELECT count(DISTINCT(key))/count(*) AS Selectivity FROM table;

## 舉例如下截取last_name前4個(gè)字符

ALTER TABLE employees.employees
ADD INDEX `first_name_last_name4` (first_name, last_name(4));

SELECT count(DISTINCT(concat(first_name, left(last_name, 4))))/count(*) AS Selectivity FROM employees.employees;

對(duì)比,值越大越好

強(qiáng)制使用某個(gè)索引

...
 FROM table_name1 a  USE INDEX (index_name1) LEFT JOIN table_name2 c 
FORCE INDEX FOR JOIN (index_name2)
...

使用explain分析索引

1、id:SQL執(zhí)行的順序的標(biāo)識(shí)。

sql從里向外執(zhí)行,sql是按照id從大到小執(zhí)行的。

2、select_type: select類(lèi)型

1)、SIMPLE(不使用UNION或子查詢(xún)等)

  1. 、PRIMARY:最外層的select

3)、DERIVED:派生表的SELECT(FROM子句的子查詢(xún))

4)、UNION:UNION中的第二個(gè)或后面的SELECT語(yǔ)句

5)、UNION RESULT:UNION的結(jié)果。

6)、DEPENDENT UNION:UNION中的第二個(gè)或后面的SELECT語(yǔ)句,取決于外面的查詢(xún)

7)、SUBQUERY:子查詢(xún)中的第一個(gè)SELECT

8)、DEPENDENT SUBQUERY:子查詢(xún)中的第一個(gè)SELECT,取決于外面的查詢(xún)

3、table:表的名字。

有時(shí)不是真實(shí)的表名字,看到的是derivedx(x是個(gè)數(shù)字,我的理解是第幾步執(zhí)行的結(jié)果)

4、type:連接操作的類(lèi)型。

這列很重要,顯示了連接使用了哪種類(lèi)別,有無(wú)使用索引。在各種類(lèi)型的關(guān)聯(lián)關(guān)系當(dāng)中,效率最高的是system,然后依次是const、eq_ref、ref、range、index和 All。一般來(lái)說(shuō),得保證查詢(xún)至少達(dá)到range級(jí)別,最好能達(dá)到ref,否則就可能會(huì)出現(xiàn)性能問(wèn)題。

1)、system

表只有一行:system表。這是const連接類(lèi)型的特殊情況

2)、const

表中的一個(gè)記錄的最大值能夠匹配這個(gè)查詢(xún)(索引可以是主鍵或惟一索引)。因?yàn)橹挥幸恍校@個(gè)值實(shí)際就是常數(shù),因?yàn)镸YSQL先讀這個(gè)值然后把它當(dāng)做常數(shù)來(lái)對(duì)待

3)、eq_ref

在連接中,MYSQL在查詢(xún)時(shí),從前面的表中,對(duì)每一個(gè)記錄的聯(lián)合都從表中讀取一個(gè)記錄,它在查詢(xún)使用了索引為主鍵或惟一鍵的全部時(shí)使用

4)、ref

這個(gè)連接類(lèi)型只有在查詢(xún)使用了不是惟一或主鍵的鍵或者是這些類(lèi)型的部分(比如,利用最左邊前綴)時(shí)發(fā)生。對(duì)于之前的表的每一個(gè)行聯(lián)合,全部記錄都將從表中讀出。這個(gè)類(lèi)型嚴(yán)重依賴(lài)于根據(jù)索引匹配的記錄多少(越少越好)

5)、range

這個(gè)連接類(lèi)型使用索引返回一個(gè)范圍中的行,比如使用>或<查找東西時(shí)發(fā)生的情況

6)、index

這個(gè)連接類(lèi)型對(duì)前面的表中的每一個(gè)記錄聯(lián)合進(jìn)行完全掃描(比ALL更好,因?yàn)樗饕话阈∮诒頂?shù)據(jù))

7)、ALL

這個(gè)連接類(lèi)型對(duì)于前面的每一個(gè)記錄聯(lián)合進(jìn)行完全掃描,這一般比較糟糕,應(yīng)該盡量避免。因?yàn)樗獟呙枵麄€(gè)表。你可以加入更多的索引來(lái)解決這個(gè)問(wèn)題。

5、possible_key:MySQL在搜索數(shù)據(jù)記錄時(shí)可以選用的各個(gè)索引名。

這里的索引名是創(chuàng)建索引時(shí)指定的索引昵稱(chēng);如果索引沒(méi)有昵稱(chēng),則默認(rèn)顯示的是索引中第一個(gè)列的名字(在上一節(jié)舉的例子中是“firstname”)。默認(rèn)索引名字的含義往往不是很明顯。

6、key:它顯示了MySQL實(shí)際使用的索引。

key數(shù)據(jù)列是MySQL實(shí)際選用的索引,如果它為空(或NULL),則MySQL不使用索引。

7、key_len:索引中被使用部分的長(zhǎng)度,以字節(jié)計(jì)。

key_len的值可以告訴你在聯(lián)合索引中mysql會(huì)真正使用了哪些索引。 在上例中,key_len是102,其中firstname占50字節(jié),lastname占50字節(jié),age占2字節(jié)(smallint存儲(chǔ)大小為2字節(jié))。如果MySQL只使用索引中的firstname部分,則key_len將是50。 在不損失精確性的情況下 ,key_len數(shù)據(jù)列里的值越小越好(意思是更快)。

8、ref:顯示使用哪個(gè)列或常數(shù)與key一起從表中選擇行。

ref數(shù)據(jù)列給出了關(guān)聯(lián)關(guān)系中另一個(gè)數(shù)據(jù)表里的數(shù)據(jù)列的名字。

9、rows:MySQL所認(rèn)為的它在找到正確的結(jié)果之前必須掃描的記錄數(shù)。

顯然,這里最理想的數(shù)字就是1。

10、extra:附加信息

Using index和Using where會(huì)遇到的比較多,可以重點(diǎn)記下,其他的我沒(méi)怎么遇到過(guò)了解即可,遇到具體問(wèn)題可以查閱哈

1)、Distinct

一旦MYSQL找到了與行相聯(lián)合匹配的行,就不再搜索了

2)、Not exists

MYSQL優(yōu)化了LEFT JOIN,一旦它找到了匹配LEFT JOIN標(biāo)準(zhǔn)的行,就不再搜索了 。

3)、Range checked for each

沒(méi)有找到理想的索引,因此對(duì)于從前面表中來(lái)的每一個(gè)行組合,MYSQL檢查使用哪個(gè)索引,并用它來(lái)從表中返回行。這是使用索引的最慢的連接之一

4)、Using filesort

看到這個(gè)的時(shí)候,查詢(xún)就需要優(yōu)化了。MYSQL需要進(jìn)行額外的步驟來(lái)發(fā)現(xiàn)如何對(duì)返回的行排序。它根據(jù)連接類(lèi)型以及存儲(chǔ)排序鍵值和匹配條件的全部行的行指針來(lái)排序全部行

5)Using index

列數(shù)據(jù)是從僅僅使用了索引中的信息而沒(méi)有讀取實(shí)際的行動(dòng)的表返回的,這發(fā)生在對(duì)表的全部的請(qǐng)求列都是同一個(gè)索引的部分的時(shí)候

6)Using temporary

看到這個(gè)的時(shí)候,查詢(xún)需要優(yōu)化了。這里,MYSQL需要?jiǎng)?chuàng)建一個(gè)臨時(shí)表來(lái)存儲(chǔ)結(jié)果,這通常發(fā)生在對(duì)不同的列集進(jìn)行ORDER BY上,而不是GROUP BY上

7)Using where

使用了WHERE從句來(lái)限制哪些行將與下一張表匹配或者是返回給用戶(hù)。如果不想返回表中的全部行,并且連接類(lèi)型ALL或index,這就會(huì)發(fā)生,或者是查詢(xún)有問(wèn)題

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容