MySQL慢查詢(xún)以及重構(gòu)查詢(xún)的方式記錄
前言
什么是慢查詢(xún),如何優(yōu)化慢查詢(xún),下面介紹這兩個(gè)知識(shí)點(diǎn)的相關(guān)知識(shí)。
慢查詢(xún)基礎(chǔ):優(yōu)化數(shù)據(jù)訪問(wèn)
是否向數(shù)據(jù)庫(kù)請(qǐng)求了不需要的數(shù)據(jù)
查詢(xún)不需要的記錄:解決方案:查詢(xún)后面加上Limit
多表關(guān)聯(lián)時(shí)返回全部列:解決方案:只取需要的列
總是取出全部列:select * 解決方案:最好還是獲取部分列,除非應(yīng)用程序處緩存列的數(shù)據(jù)了
重復(fù)查詢(xún)相同的數(shù)據(jù):解決方案:需要時(shí)從緩存中取出
MySQL是否在掃描額外的記錄
可以從響應(yīng)時(shí)間,掃描的行數(shù),返回的行數(shù)來(lái)進(jìn)行查詢(xún)開(kāi)銷(xiāo)的衡量。
要想減少掃描行數(shù)可以使用索引對(duì)需要的記錄進(jìn)行覆蓋,但是增加索引不意味著就能讓掃描的行數(shù)等于返回的行數(shù),比如sum,count之類(lèi)的聚合函數(shù)
重構(gòu)查詢(xún)的方法
一個(gè)復(fù)雜查詢(xún)還是多個(gè)簡(jiǎn)單查詢(xún)
在過(guò)去,總是強(qiáng)調(diào)需要數(shù)據(jù)庫(kù)層完成盡可能多的工作,因?yàn)檫^(guò)去網(wǎng)絡(luò)通信查詢(xún)解析和優(yōu)化是一件代價(jià)很高的事情。
但是這樣的想法對(duì)于MySQL并不適用,MySQL從設(shè)計(jì)上讓連接和斷開(kāi)連接都很輕量級(jí),在返回一個(gè)小的查詢(xún)結(jié)果方面很高效?,F(xiàn)代的網(wǎng)絡(luò)速度比以前要快很多,無(wú)論是帶寬還是延遲。在某些版本的MySQL上,即使在一個(gè)通用服務(wù)器上,也能夠運(yùn)行每秒超過(guò)10萬(wàn)的查詢(xún),即使是一個(gè)千兆網(wǎng)卡也能輕松滿(mǎn)足每秒超過(guò)2000次的查詢(xún)。所以運(yùn)行多個(gè)小查詢(xún)現(xiàn)在已經(jīng)不是大問(wèn)題了。
當(dāng)然,相比較于內(nèi)部掃描,響應(yīng)數(shù)據(jù)給客戶(hù)端更加耗時(shí),所以在同條件下,使用盡可能少的查詢(xún)更好。
切分查詢(xún)
當(dāng)使用sql進(jìn)行查詢(xún)時(shí),需要注意將大查詢(xún)切分成小查詢(xún),可以減少對(duì)數(shù)據(jù)庫(kù)的影響,因?yàn)橐粋€(gè)大語(yǔ)句一次性完成的話,則可能一次鎖住很多數(shù)據(jù),占滿(mǎn)整個(gè)事務(wù)日志,耗盡系統(tǒng)資源,阻塞其他查詢(xún)。
比如我們做數(shù)據(jù)統(tǒng)計(jì)時(shí)要對(duì)大量訂單號(hào)的信息進(jìn)行查詢(xún),那么是一次性用in查詢(xún),還是切割參數(shù)list多次查詢(xún)呢,答案是切割參數(shù)list多次查詢(xún),因?yàn)楫?dāng)in里面的參數(shù)過(guò)多時(shí),MySQL就會(huì)認(rèn)為再走索引已經(jīng)不行了,可能就會(huì)進(jìn)行全表查詢(xún),如果這個(gè)時(shí)候數(shù)據(jù)表數(shù)據(jù)量過(guò)大,那可能就會(huì)造成查詢(xún)超時(shí)。
// chops a list into non-view sublists of length L static <T> List<List<T>> chopped(List<T> list, final int L) { List<List<T>> parts = new ArrayList<List<T>>(); final int N = list.size(); for (int i = 0; i < N; i += L) { parts.add(new ArrayList<T>( list.subList(i, Math.min(N, i + L))) ); } return parts; } List<Integer> numbers = Collections.unmodifiableList( Arrays.asList(5,3,1,2,9,5,0,7) ); List<List<Integer>> parts = chopped(numbers, 3); System.out.println(parts); // prints "[[5, 3, 1], [2, 9, 5], [0, 7]]" parts.get(0).add(-1); System.out.println(parts); // prints "[[5, 3, 1, -1], [2, 9, 5], [0, 7]]" System.out.println(numbers); // prints "[5, 3, 1, 2, 9, 5, 0, 7]" (unmodified!)
在程序中將list截?cái)啵瑥亩共樵?xún)能使用索引而不是進(jìn)行全表掃描。
阿里開(kāi)發(fā)手冊(cè)中就推薦仔細(xì)評(píng)估in后面的集合元素?cái)?shù)量,控制在1000個(gè)之內(nèi)。
分解關(guān)聯(lián)查詢(xún)
將多表inner join 進(jìn)行分解,分解成小查詢(xún),超過(guò)三個(gè)表的join,就需要禁止了。
優(yōu)點(diǎn)有:
- 緩存的效率會(huì)更高,
- 分解后的查詢(xún)可以減少鎖的競(jìng)爭(zhēng)
- 應(yīng)用層可以緩存查詢(xún)數(shù)據(jù),減小數(shù)據(jù)庫(kù)的壓力。
- 可以提升查詢(xún)效率,因?yàn)橛弥麈I之類(lèi)進(jìn)行in查詢(xún),比按照條件范圍查詢(xún)可能會(huì)更高效,尤其是大表的時(shí)候。
- 可以減少冗余記錄的查詢(xún)
- 更進(jìn)一步,這樣做相當(dāng)于在應(yīng)用中實(shí)現(xiàn)了哈希關(guān)聯(lián),而不是使用MySQL的嵌套循環(huán)關(guān)聯(lián)。某些場(chǎng)景哈希關(guān)聯(lián)的效率要高很多。
總結(jié)
到此這篇關(guān)于MySQL慢查詢(xún)以及重構(gòu)查詢(xún)的文章就介紹到這了,更多相關(guān)MySQL慢查詢(xún)重構(gòu)查詢(xún)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
mysql服務(wù)無(wú)法啟動(dòng)報(bào)錯(cuò)誤1067解決方法(mysql啟動(dòng)錯(cuò)誤1067 )
mysql服務(wù)無(wú)法啟動(dòng)報(bào)錯(cuò)誤1067解決方法,大家參考使用吧2013-12-12關(guān)于mysql數(shù)據(jù)庫(kù)格式化簡(jiǎn)單介紹
本文將介紹關(guān)于mysql數(shù)據(jù)庫(kù)格式化時(shí)需要注意的一些問(wèn)題,需要的朋友可以參考下2012-11-11一文弄懂MySQL中redo?log與binlog的區(qū)別
在學(xué)習(xí)mysql數(shù)據(jù)庫(kù)時(shí),不可避免要去接觸到redo log和binlog,好多人對(duì)這兩者的概念分不太清,下面這篇文章主要給大家介紹了關(guān)于MySQL中redo?log與binlog區(qū)別的相關(guān)資料,需要的朋友可以參考下2022-02-02MySQL中將逗號(hào)分隔的字段轉(zhuǎn)換為多行數(shù)據(jù)的方法
在我們的實(shí)際開(kāi)發(fā)中,經(jīng)常需要存儲(chǔ)一些字段,它們使用像,?-?等連接符進(jìn)行連接,在查詢(xún)過(guò)程中,有時(shí)需要將這些字段使用連接符分割,然后查詢(xún)多條數(shù)據(jù),今天,我們將使用一個(gè)實(shí)際的生產(chǎn)場(chǎng)景來(lái)詳細(xì)解釋這個(gè)解決方案,需要的朋友可以參考下2024-04-04MySQL數(shù)據(jù)庫(kù)事務(wù)隔離級(jí)別詳解
這篇文章主要介紹了MySQL數(shù)據(jù)庫(kù)事務(wù)隔離級(jí)別詳解的相關(guān)資料,需要的朋友可以參考下2017-03-03Mysql百萬(wàn)級(jí)分頁(yè)優(yōu)化技巧
這篇文章主要介紹了Mysql百萬(wàn)級(jí)分頁(yè)優(yōu)化技巧,包括普通分頁(yè)和優(yōu)化分頁(yè)兩種,在數(shù)據(jù)量比較大的時(shí)候,我們盡量去利用索引來(lái)優(yōu)化語(yǔ)句。下面通過(guò)本文給大家詳細(xì)講解,一起看看吧2016-12-12