MySQL 優(yōu)化
表關(guān)聯(lián)查詢時(shí)務(wù)必遵循?小表驅(qū)動(dòng)大表?原則;
使用查詢語(yǔ)句?where?條件時(shí),不允許出現(xiàn)?函數(shù),否則索引會(huì)失效;
使用單表查詢時(shí),相同字段盡量不要用?OR,因?yàn)榭赡軐?dǎo)致索引失效,比如:SELECT * FROM table WHERE name = '手機(jī)' OR name = '電腦',可以使用?UNION?替代;
LIKE?語(yǔ)句不允許使用?%?開(kāi)頭,否則索引會(huì)失效;
組合索引一定要遵循?從左到右?原則,否則索引會(huì)失效;比如:SELECT * FROM table WHERE name = '張三' AND age = 18,那么該組合索引必須是?name,age?形式;
索引不宜過(guò)多,根據(jù)實(shí)際情況決定,盡量不要超過(guò) 10 個(gè);
每張表都必須有?主鍵,達(dá)到加快查詢效率的目的;
分表,可根據(jù)業(yè)務(wù)字段尾數(shù)中的個(gè)位或十位或百位(以此類推)做表名達(dá)到分表的目的;
分庫(kù),可根據(jù)業(yè)務(wù)字段尾數(shù)中的個(gè)位或十位或百位(以此類推)做庫(kù)名達(dá)到分庫(kù)的目的;
表分區(qū),類似于硬盤分區(qū),可以將某個(gè)時(shí)間段的數(shù)據(jù)放在分區(qū)里,加快查詢速度,可以配合?分表 + 表分區(qū)?結(jié)合使用;
#神器?EXPLAIN?語(yǔ)句
EXPLAIN?顯示了 MySQL 如何使用索引來(lái)處理?SELECT?語(yǔ)句以及連接表??梢詭椭x擇更好的索引和寫出更優(yōu)化的查詢語(yǔ)句。
使用方法,在?SELECT?語(yǔ)句前加上?EXPLAIN?即可,如:
EXPLAIN SELECT * FROM tb_item WHERE cid IN (SELECT id FROM tb_item_cat)

id:?SELECT 識(shí)別符。這是 SELECT 的查詢序列號(hào)
select_type:?SELECT類型,可以為以下任何一種
SIMPLE: 簡(jiǎn)單 SELECT(不使用 UNION 或子查詢)
PRIMARY: 最外面的 SELECT
UNION: UNION 中的第二個(gè)或后面的 SELECT 語(yǔ)句
DEPENDENT UNION: UNION 中的第二個(gè)或后面的 SELECT 語(yǔ)句,取決于外面的查詢
UNION RESULT: UNION 的結(jié)果
SUBQUERY: 子查詢中的第一個(gè) SELECT
DEPENDENT SUBQUERY: 子查詢中的第一個(gè) SELECT,取決于外面的查詢
DERIVED: 導(dǎo)出表的 SELECT(FROM 子句的子查詢)
table:?輸出的行所引用的表
partitions:?表分區(qū)
type:?聯(lián)接類型。下面給出各種聯(lián)接類型,按照?從最佳類型到最壞類型?進(jìn)行排序
system: 表僅有一行(=系統(tǒng)表)。這是 const 聯(lián)接類型的一個(gè)特例。
const: 表最多有一個(gè)匹配行,它將在查詢開(kāi)始時(shí)被讀取。因?yàn)閮H有一行,在這行的列值可被優(yōu)化器剩余部分認(rèn)為是常數(shù)。const 表很快,因?yàn)樗鼈冎蛔x取一次!
eq_ref: 對(duì)于每個(gè)來(lái)自于前面的表的行組合, 從該表中讀取一行。這可能是最好的聯(lián)接類型, 除了 const 類型。
ref: 對(duì)于每個(gè)來(lái)自于前面的表的行組合, 所有有匹配索引值的行將從這張表中讀取。
ref_or_null: 該聯(lián)接類型如同 ref,但是添加了 MySQL 可以專門搜索包含 NULL 值的行。
index_merge: 該聯(lián)接類型表示使用了索引合并優(yōu)化方法。
unique_subquery: 該類型替換了下面形式的 IN 子查詢的 ref:?value IN (SELECT primary_key FROM single_table WHERE some_expr) unique_subquery?是一個(gè)索引查找函數(shù), 可以完全替換子查詢, 效率更高。
index_subquery: 該聯(lián)接類型類似于 unique_subquery??梢蕴鎿Q IN 子查詢, 但只適合下列形式的子查詢中的非唯一索引:?value IN (SELECT key_column FROM single_table WHERE some_expr)
range: 只檢索給定范圍的行,使用一個(gè)索引來(lái)選擇行。
index: 該聯(lián)接類型與 ALL 相同,除了只有索引樹(shù)被掃描。這通常比 ALL 快,因?yàn)樗饕募ǔ1葦?shù)據(jù)文件小。
ALL: 對(duì)于每個(gè)來(lái)自于先前的表的行組合, 進(jìn)行完整的表掃描。
possible_keys:?指出 MySQL 能使用哪個(gè)索引在該表中找到行
key:?顯示 MySQL 實(shí)際決定使用的鍵(索引)。如果沒(méi)有選擇索引, 鍵是 NULL。
key_len:?顯示 MySQL 決定使用的鍵長(zhǎng)度。如果鍵是 NULL, 則長(zhǎng)度為 NULL。
ref:?顯示使用哪個(gè)列或常數(shù)與 key 一起從表中選擇行。
rows:?顯示 MySQL 認(rèn)為它執(zhí)行查詢時(shí)必須檢查的行數(shù)。多行之間的數(shù)據(jù)相乘可以估算要處理的行數(shù)。
filtered:?顯示了通過(guò)條件過(guò)濾出的行數(shù)的百分比估計(jì)值。
Extra:?該列包含 MySQL 解決查詢的詳細(xì)信息
Distinct: MySQL 發(fā)現(xiàn)第 1 個(gè)匹配行后,停止為當(dāng)前的行組合搜索更多的行。
Not exists: MySQL 能夠?qū)Σ樵冞M(jìn)行 LEFT JOIN 優(yōu)化, 發(fā)現(xiàn) 1 個(gè)匹配 LEFT JOIN 標(biāo)準(zhǔn)的行后, 不再為前面的的行組合在該表內(nèi)檢查更多的行。
range checked for each record (index map: #): MySQL 沒(méi)有發(fā)現(xiàn)好的可以使用的索引, 但發(fā)現(xiàn)如果來(lái)自前面的表的列值已知, 可能部分索引可以使用。
Using filesort: MySQL 需要額外的一次傳遞, 以找出如何按排序順序檢索行。
Using index: 從只使用索引樹(shù)中的信息而不需要進(jìn)一步搜索讀取實(shí)際的行來(lái)檢索表中的列信息。
Using temporary: 為了解決查詢, MySQL 需要?jiǎng)?chuàng)建一個(gè)臨時(shí)表來(lái)容納結(jié)果。
Using where: WHERE 子句用于限制哪一個(gè)行匹配下一個(gè)表或發(fā)送到客戶。
Using sort_union(...), Using union(...), Using intersect(...): 這些函數(shù)說(shuō)明如何為 index_merge 聯(lián)接類型合并索引掃描。
Using index for group-by: 類似于訪問(wèn)表的 Using index 方式,Using index for group-by 表示 MySQL 發(fā)現(xiàn)了一個(gè)索引,可以用來(lái)查詢 GROUP BY 或 DISTINCT 查詢的所有列, 而不要額外搜索硬盤訪問(wèn)實(shí)際的表。