MySQL 優(yōu)化
表關(guān)聯(lián)查詢時務(wù)必遵循小表驅(qū)動大表原則玷禽;
使用查詢語句where條件時赫段,不允許出現(xiàn)函數(shù),否則索引會失效矢赁;
使用單表查詢時糯笙,相同字段盡量不要用OR,因?yàn)榭赡軐?dǎo)致索引失效撩银,比如:SELECT * FROM table WHERE name = '手機(jī)' OR name = '電腦'给涕,可以使用UNION替代;
LIKE語句不允許使用%開頭额获,否則索引會失效够庙;
組合索引一定要遵循從左到右原則,否則索引會失效抄邀;比如:SELECT * FROM table WHERE name = '張三' AND age = 18耘眨,那么該組合索引必須是name,age形式;
索引不宜過多境肾,根據(jù)實(shí)際情況決定剔难,盡量不要超過 10 個;
每張表都必須有主鍵准夷,達(dá)到加快查詢效率的目的钥飞;
分表,可根據(jù)業(yè)務(wù)字段尾數(shù)中的個位或十位或百位(以此類推)做表名達(dá)到分表的目的衫嵌;
分庫读宙,可根據(jù)業(yè)務(wù)字段尾數(shù)中的個位或十位或百位(以此類推)做庫名達(dá)到分庫的目的;
表分區(qū)楔绞,類似于硬盤分區(qū)结闸,可以將某個時間段的數(shù)據(jù)放在分區(qū)里唇兑,加快查詢速度,可以配合分表 + 表分區(qū)結(jié)合使用
神器 EXPLAIN 語句
EXPLAIN顯示了 MySQL 如何使用索引來處理SELECT語句以及連接表桦锄≡剑可以幫助選擇更好的索引和寫出更優(yōu)化的查詢語句。
使用方法结耀,在SELECT語句前加上EXPLAIN即可留夜,如:
EXPLAIN SELECT * FROM tb_item WHERE cid IN (SELECT id FROM tb_item_cat)
id:SELECT 識別符。這是 SELECT 的查詢序列號
select_type:SELECT類型,可以為以下任何一種
SIMPLE: 簡單 SELECT(不使用 UNION 或子查詢)
PRIMARY: 最外面的 SELECT
UNION: UNION 中的第二個或后面的 SELECT 語句
DEPENDENT UNION: UNION 中的第二個或后面的 SELECT 語句,取決于外面的查詢
UNION RESULT: UNION 的結(jié)果
SUBQUERY: 子查詢中的第一個 SELECT
DEPENDENT SUBQUERY: 子查詢中的第一個 SELECT,取決于外面的查詢
DERIVED: 導(dǎo)出表的 SELECT(FROM 子句的子查詢)
table:輸出的行所引用的表
partitions:表分區(qū)
type:聯(lián)接類型图甜。下面給出各種聯(lián)接類型碍粥,按照從最佳類型到最壞類型進(jìn)行排序
system: 表僅有一行(=系統(tǒng)表)。這是 const 聯(lián)接類型的一個特例黑毅。
const: 表最多有一個匹配行,它將在查詢開始時被讀取嚼摩。因?yàn)閮H有一行,在這行的列值可被優(yōu)化器剩余部分認(rèn)為是常數(shù)。const 表很快,因?yàn)樗鼈冎蛔x取一次!
eq_ref: 對于每個來自于前面的表的行組合, 從該表中讀取一行矿瘦。這可能是最好的聯(lián)接類型, 除了 const 類型枕面。
ref: 對于每個來自于前面的表的行組合, 所有有匹配索引值的行將從這張表中讀取。
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是一個索引查找函數(shù), 可以完全替換子查詢, 效率更高。
index_subquery: 該聯(lián)接類型類似于 unique_subquery病游〈娇纾可以替換 IN 子查詢, 但只適合下列形式的子查詢中的非唯一索引:value IN (SELECT key_column FROM single_table WHERE some_expr)
range: 只檢索給定范圍的行,使用一個索引來選擇行稠通。
index: 該聯(lián)接類型與 ALL 相同,除了只有索引樹被掃描衬衬。這通常比 ALL 快,因?yàn)樗饕募ǔ1葦?shù)據(jù)文件小。
ALL: 對于每個來自于先前的表的行組合, 進(jìn)行完整的表掃描改橘。
possible_keys:指出 MySQL 能使用哪個索引在該表中找到行
key:顯示 MySQL 實(shí)際決定使用的鍵(索引)滋尉。如果沒有選擇索引, 鍵是 NULL。
key_len:顯示 MySQL 決定使用的鍵長度飞主。如果鍵是 NULL, 則長度為 NULL狮惜。
ref:顯示使用哪個列或常數(shù)與 key 一起從表中選擇行。
rows:顯示 MySQL 認(rèn)為它執(zhí)行查詢時必須檢查的行數(shù)碌识。多行之間的數(shù)據(jù)相乘可以估算要處理的行數(shù)碾篡。
filtered:顯示了通過條件過濾出的行數(shù)的百分比估計值。
Extra:該列包含 MySQL 解決查詢的詳細(xì)信息
Distinct: MySQL 發(fā)現(xiàn)第 1 個匹配行后,停止為當(dāng)前的行組合搜索更多的行筏餐。
Not exists: MySQL 能夠?qū)Σ樵冞M(jìn)行 LEFT JOIN 優(yōu)化, 發(fā)現(xiàn) 1 個匹配 LEFT JOIN 標(biāo)準(zhǔn)的行后, 不再為前面的的行組合在該表內(nèi)檢查更多的行开泽。
range checked for each record (index map: #): MySQL 沒有發(fā)現(xiàn)好的可以使用的索引, 但發(fā)現(xiàn)如果來自前面的表的列值已知, 可能部分索引可以使用。
Using filesort: MySQL 需要額外的一次傳遞, 以找出如何按排序順序檢索行魁瞪。
Using index: 從只使用索引樹中的信息而不需要進(jìn)一步搜索讀取實(shí)際的行來檢索表中的列信息穆律。
Using temporary: 為了解決查詢, MySQL 需要創(chuàng)建一個臨時表來容納結(jié)果惠呼。
Using where: WHERE 子句用于限制哪一個行匹配下一個表或發(fā)送到客戶。
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 查詢的所有列, 而不要額外搜索硬盤訪問實(shí)際的表剔蹋。