上篇回顧
繼上兩篇:
MySQL慢查詢(中):正確的處理姿勢,你get到了嗎诈乒?
在以上兩篇內(nèi)容中,我們一起探索了這些內(nèi)容:
1)SQL執(zhí)行過程
2)查詢SQL為什么會慢
3)如何定位查詢問題
4)幾種實(shí)用解決方案介紹
如果將MySQL慢查詢作為一個問題來拆解分析的話婆芦,之前上怕磨、中篇章算是問題分析、問題定位和解決消约,那今天來跟大家收下尾肠鲫,聊聊MySQL慢查詢問題解決經(jīng)驗(yàn)總結(jié)。
廢話不多說或粮,直接開干~
高性能查詢難題優(yōu)化總結(jié)
我們來總結(jié)一下导饲,應(yīng)該如何處理高性能查詢難題?
假如把高性能查詢比作一個“難題”氯材,它其實(shí)是包括多個子難題在內(nèi)渣锦,共同作用的結(jié)果。
今天我們來歸納總結(jié)下氢哮,主要包括以下幾類:
1 數(shù)據(jù)結(jié)構(gòu)優(yōu)化
良好的schema設(shè)計(jì)原則是普遍適用的袋毙,但是MySQL有他自己的實(shí)現(xiàn)細(xì)節(jié)要注意,概況來講冗尤,盡可能保持任何東西小而簡單總是好的听盖。
主要有以下簡單的原則值得你去考慮使用:
1)盡量避免過度設(shè)計(jì)
2)使用小而簡單的合適數(shù)據(jù)類型胀溺,盡可能避免使用null
3)盡量使用相同的數(shù)據(jù)類型存儲相似或者相關(guān)的值
4)注意可變長字符串,其在臨時(shí)表和排序時(shí)可能按最大長度分配內(nèi)存
5)盡量使用整形定義標(biāo)識符
2 索引設(shè)計(jì)優(yōu)化
常見的B-Tree索引皆看,按照順序存儲數(shù)據(jù)仓坞,所以MySQL可以用來做ORDER BY 和 GROUP BY操作。因?yàn)閿?shù)據(jù)是有序的腰吟,所以便于將相關(guān)的列值都存儲在一起扯躺。由于索引中存儲了實(shí)際的列值,所以一些查詢只通過索引就能夠完成查詢(如:聚簇索引)蝎困。
根據(jù)索引的特性录语,總結(jié)索引的優(yōu)點(diǎn)有如下幾點(diǎn):
1)減少服務(wù)器需要掃描的數(shù)據(jù)量;
2)幫助服務(wù)器避免排序和臨時(shí)表禾乘;
3)將隨機(jī)I/O變?yōu)轫樞騃/O澎埠。
編寫查詢語句時(shí)候應(yīng)該注意盡可能選擇合適的索引,以避免單行查找始藕,盡可能使用索引覆蓋蒲稳。
根據(jù)執(zhí)行計(jì)劃依次掃描相關(guān)表中的行,不在數(shù)據(jù)緩沖區(qū)的走IO存儲引擎掃描表的性能消耗參考下面的list伍派,消耗從大到薪:
全表掃描>全索引掃描>部分索引掃描>索引查找>唯一索引/主鍵查找>常量/null
應(yīng)用查詢優(yōu)化是建立在良好的數(shù)據(jù)結(jié)構(gòu)和合理的索引設(shè)計(jì)之上的。
它主要包括以下幾種情況:
2.1 重構(gòu)查詢方式
優(yōu)化慢查詢時(shí)诉植,目標(biāo)應(yīng)該是找到一個更優(yōu)的方案來達(dá)到我們獲取結(jié)果數(shù)據(jù)的目的祥国。其中可以存在多樣的權(quán)衡方案:
1)從數(shù)據(jù)庫中查詢計(jì)算直接獲取到結(jié)果數(shù)據(jù);
2)拆分多條子查詢來逐步得到結(jié)果數(shù)據(jù)晾腔;
3)從數(shù)據(jù)庫獲取到基礎(chǔ)數(shù)據(jù)舌稀,然后應(yīng)用代碼邏輯加工后獲得結(jié)果數(shù)據(jù)。
2.2 讓SQL盡量符合查詢優(yōu)化器的執(zhí)行要求
MySQL 查詢優(yōu)化器并不是對所有查詢都適用的灼擂,我們可以通過改寫查詢 SQL 來讓數(shù)據(jù)庫更高效的完成工作壁查。
常見查詢應(yīng)用優(yōu)化建議匯總?cè)缦拢?/p>
1)對于任何查詢,應(yīng)盡量避免全表掃描
????首先應(yīng)考慮在 where 及 order by 涉及的列上建立并應(yīng)用索引剔应;
2)盡量避免在 where 子句中進(jìn)行操作
????使用 or 來連接條件睡腿、對字段進(jìn)行 null 值判斷、匹配查詢 '%abc%'峻贮、!= 或 <> 操作符席怪,否則將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描;
3)盡量應(yīng)用索引
? ? 使用索引字段作為條件時(shí)月洛,如果是復(fù)合索引何恶,那么必須使用到該索引中的第一個字段作為條件時(shí)才能保證系統(tǒng)使用該索引,否則該索引將不會被使用嚼黔,并且應(yīng)盡可能的讓字段順序與索引順序相一致细层;
4)索引字段要注意慎重選取
????索引盡量避開區(qū)分度不大的字段惜辑,如:sex、male疫赎、female?
? ? 這種五五開的索引列有大量數(shù)據(jù)重復(fù)時(shí)盛撑,那么即使在 sex 上建了索引也對查詢效率起不了作用。
5)一個表的索引數(shù)最好不要超過 6 個
????索引并不是越多越好捧搞,索引固然可以提高相應(yīng)的 select 的效率抵卫,但同時(shí)也降低了 insert 及 update 的效率, 因?yàn)?insert 或 update 時(shí)有可能會重建索引胎撇,所以怎樣建索引需要慎重考慮介粘,視具體情況而定。
6)盡量使用數(shù)字型字段
????若只含數(shù)值信息的字段盡量不要設(shè)計(jì)為字符型晚树,這會降低查詢和連接的性能姻采,并會增加存儲開銷。?這是因?yàn)橐嬖谔幚聿樵兒瓦B接時(shí)會逐個比較字符串中每一個字符爵憎,而對于數(shù)字型而言只需要比較一次就夠了慨亲。
7)盡量避免使用 *
??? select * from table ,用具體的字段列表代替 *宝鼓,不要返回用不到的任何字段刑棵,尤其是多表關(guān)聯(lián)查詢的情況。
MySQL v5.6版本以后愚铡,消除了很多MySQL原本的限制蛉签,讓更多的查詢能夠以盡可能高的效率完成。
小結(jié)
良好的表結(jié)構(gòu)設(shè)計(jì)是高性能查詢的基石茂附,恰當(dāng)?shù)乃饕O(shè)計(jì)是高性能查詢的助推器正蛙,同時(shí)合理的查詢應(yīng)用也是必不可少的。數(shù)據(jù)結(jié)構(gòu)優(yōu)化营曼、索引設(shè)計(jì)優(yōu)化及應(yīng)用查詢優(yōu)化猶如三叉戟一般,齊頭并進(jìn)愚隧,在高性能查詢應(yīng)用中缺一不可蒂阱。
寫在最后
全文總結(jié)一下,其實(shí)就是我們要學(xué)會用數(shù)據(jù)庫的要求方式來執(zhí)行SQL狂塘。
即要寫好應(yīng)用查詢SQL录煤,必須要結(jié)合良好的數(shù)據(jù)結(jié)構(gòu)和合理的索引設(shè)計(jì)才可以。
其實(shí)MySQL查詢優(yōu)化中的每一項(xiàng)拆開講都可以是很大的章節(jié)荞胡,在此主要是將解決問題的思路分享給大家妈踊,希望能對大家今后的工作中能有所幫助。
最后泪漂,感謝大家的持續(xù)關(guān)注~
作者:架構(gòu)精進(jìn)之路廊营,專注軟件架構(gòu)研究歪泳,技術(shù)學(xué)習(xí)與個人成長,關(guān)注并私信我回復(fù)“01”露筒,送你一份程序員成長進(jìn)階大禮包呐伞。
Thanks for reading!