mysql聚合統(tǒng)計(jì)數(shù)據(jù)查詢緩慢的優(yōu)化方法
寫在前面
在我們?nèi)粘2僮鲾?shù)據(jù)庫的時(shí)候,比如訂單表、訪問記錄表、商品表的時(shí)候。
經(jīng)常會(huì)處理計(jì)算數(shù)據(jù)列總和、數(shù)據(jù)行數(shù)等統(tǒng)計(jì)問題。
隨著業(yè)務(wù)發(fā)展,這些表會(huì)越來越大,如果處理不當(dāng),查詢統(tǒng)計(jì)的速度也會(huì)越來越慢,直到業(yè)務(wù)無法再容忍。
所以,我們需要先了解、思考這些場(chǎng)景知識(shí)點(diǎn),在設(shè)計(jì)之初,便預(yù)留一些優(yōu)化空間支撐業(yè)務(wù)發(fā)展。
sql聚合函數(shù)
在mysql等數(shù)據(jù)中,都會(huì)支持聚合函數(shù),方便我們計(jì)算數(shù)據(jù)。
常見的有以下方法
取平均值 AVG()
求和 SUM()
最大值 MAX()
最小值 MIN()
行數(shù) COUNT()
演示幾個(gè)簡(jiǎn)單使用的sql語句:
查詢u_id為100的訂單總數(shù)
select count(id) from orders where u_id = 100;
查詢u_id為100的訂單消費(fèi)總和
select sum(order_amount) from orders where u_id = 100;
查詢銷量最高的商品
select max(sell_num) from goods
統(tǒng)計(jì)7月份的訂單數(shù)量、金額總和
select count(id) as count, sum(order_amount) as total_amount from orders where order_date between 20190701 and 20190731 and is_pay = 1
如果此時(shí),訂單表的總數(shù)是1億條。并且此條sql運(yùn)行很慢,我們應(yīng)該如何排查優(yōu)化?
有的同學(xué)會(huì)說了:行數(shù)多,在日期字段上加 索引,這樣子篩選就很快了。
總數(shù)1億條,假設(shè)7月份的訂單有1000萬條,加了索引的時(shí)候,篩選速度自然會(huì)提升不少。但是此時(shí)我們的問題真的解決了嗎?
在這種聚合函數(shù)中,結(jié)果需要 遍歷每一條 數(shù)據(jù)來計(jì)算,比如我們統(tǒng)計(jì)訂單總和,就需要每一行都讀取訂單金額,然后加起來。
也就是說在這條統(tǒng)計(jì)sql中,需要先從1億數(shù)據(jù)中篩選1000萬條數(shù)據(jù),然后再遍歷這些數(shù)據(jù)來計(jì)算。 此時(shí)就會(huì)非常慢了。
增加索引并不能解決聚合函數(shù)統(tǒng)計(jì)慢的問題
優(yōu)化聚合統(tǒng)計(jì)的方案
提前預(yù)算
建立 統(tǒng)計(jì)數(shù)據(jù)表,以日期區(qū)分,如:20190801一天,銷售了多少訂單、金額等等數(shù)據(jù)。
當(dāng)訂單產(chǎn)生(支付完成后 可統(tǒng)計(jì)數(shù)據(jù))時(shí),便在統(tǒng)計(jì)數(shù)據(jù)表中對(duì)應(yīng)的日期增加金額、數(shù)量。
需要注意的是,如果有退款等場(chǎng)景會(huì)影響減少數(shù)據(jù),記得也相應(yīng)地做操作處理
當(dāng)我們需要統(tǒng)計(jì)8月份的數(shù)據(jù)時(shí)候,則只需要遍歷計(jì)算這一個(gè)月的三十來行數(shù)據(jù)。
定時(shí)落地
我們可以使用easyswoole、計(jì)劃任務(wù)等。來定時(shí)(比如每20分鐘一次)計(jì)算總和,然后更新到 統(tǒng)計(jì)數(shù)據(jù)表 中。
優(yōu)點(diǎn):做的處理比較少,也無需改動(dòng)退款操作等api,只需要依賴 原訂單 表的數(shù)據(jù),定時(shí)統(tǒng)計(jì)、刷新統(tǒng)計(jì)數(shù)據(jù)。
需要注意的是,根據(jù)不同的訂單熱度,來設(shè)置不同的落地頻率,比如 一周內(nèi)的數(shù)據(jù)變化幾率比較大,可能20分鐘落地。而一年前的數(shù)據(jù)則變化幾率很小,可以選擇某天同步一次,甚至確保不會(huì)變動(dòng)時(shí),則不再刷新。
總結(jié)
索引并不能解決統(tǒng)計(jì)聚合數(shù)據(jù)慢的sql語句問題
聚合函數(shù)謹(jǐn)慎用 最好不用,因?yàn)槲覀儫o法預(yù)算以后的數(shù)據(jù)量需要掃描多少行數(shù)據(jù)來計(jì)算
優(yōu)化方案離不開統(tǒng)計(jì)表,都需要按一定的周期儲(chǔ)存運(yùn)算好的統(tǒng)計(jì)數(shù)據(jù)
到此這篇關(guān)于mysql聚合統(tǒng)計(jì)數(shù)據(jù)查詢緩慢的文章就介紹到這了,更多相關(guān)mysql聚合統(tǒng)計(jì)數(shù)據(jù)查詢緩慢內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- php、mysql查詢當(dāng)天,查詢本周,查詢本月的數(shù)據(jù)實(shí)例(字段是時(shí)間戳)
- mysql中獲取一天、一周、一月時(shí)間數(shù)據(jù)的各種sql語句寫法
- MySQL如何統(tǒng)計(jì)一個(gè)數(shù)據(jù)庫所有表的數(shù)據(jù)量
- laravel實(shí)現(xiàn)按月或天或小時(shí)統(tǒng)計(jì)mysql數(shù)據(jù)的方法
- 詳解mysql 獲取某個(gè)時(shí)間段每一天、每一個(gè)小時(shí)的統(tǒng)計(jì)數(shù)據(jù)
- mysql按照天統(tǒng)計(jì)報(bào)表當(dāng)天沒有數(shù)據(jù)填0的實(shí)現(xiàn)代碼
- mysql 獲取規(guī)定時(shí)間段內(nèi)的統(tǒng)計(jì)數(shù)據(jù)
- MySql按時(shí),天,周,月進(jìn)行數(shù)據(jù)統(tǒng)計(jì)
相關(guān)文章
MySQL 數(shù)據(jù)庫對(duì)服務(wù)器端光標(biāo)的限制
從MySQL 5.0.2開始,通過mysql_stmt_attr_set() C API函數(shù)實(shí)現(xiàn)了服務(wù)器端光標(biāo)。服務(wù)器端光標(biāo)允許在服務(wù)器端生成結(jié)果集,但不會(huì)將其傳輸?shù)娇蛻舳?,除非客戶端?qǐng)求這些行。2009-03-03選擇MySQL數(shù)據(jù)庫的命令以及PHP腳本下的操作方法
這篇文章主要介紹了選擇MySQL數(shù)據(jù)庫的命令以及PHP腳本下的操作方法,此外文中還對(duì)MySQL的基本數(shù)據(jù)類型作了介紹,需要的朋友可以參考下2015-11-11Mysql通過ibd文件恢復(fù)數(shù)據(jù)的詳細(xì)步驟
mysql在使用的過程中,難免遇到數(shù)據(jù)庫表誤操作,下面這篇文章主要給大家介紹了關(guān)于Mysql通過ibd文件恢復(fù)數(shù)據(jù)的詳細(xì)步驟,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-06-06MySql中modify、rename、change的使用及區(qū)別
這篇文章主要介紹了MySql中modify、rename、change的使用及區(qū)別,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-06-06MySQL8設(shè)置自動(dòng)創(chuàng)建時(shí)間和自動(dòng)更新時(shí)間的實(shí)現(xiàn)方法
在實(shí)際應(yīng)用中,我們時(shí)常會(huì)需要用到創(chuàng)建時(shí)間和更新時(shí)間這兩個(gè)字段,下面這篇文章主要給大家介紹了關(guān)于MySQL8設(shè)置自動(dòng)創(chuàng)建時(shí)間和自動(dòng)更新時(shí)間的實(shí)現(xiàn)方法,需要的朋友可以參考下2023-03-03mysql 服務(wù)意外停止1067錯(cuò)誤解決辦法小結(jié)
今天在配置服務(wù)器時(shí)安裝mysql5.5總是無法安裝,查看日志錯(cuò)誤提示為1067錯(cuò)誤,下面來看我的解決辦法2012-11-11