摘要:記住它,一點點來,萬物均可優(yōu)化。下一篇將為你講解對一個萬數(shù)據(jù)的表程序優(yōu)化實戰(zhàn)真實例子之二開刀數(shù)據(jù)表完本文原創(chuàng)發(fā)布于微信公眾號北哥小報嚴謹?shù)脑瓌?chuàng)技術(shù)文,還有一些其他研究。
當前系統(tǒng)情況這是一篇真實案例,并不是理論課,阿北將同步我的整個優(yōu)化之路,優(yōu)化之路慢慢長,對大家拋磚引玉已達目的,若你也有一些優(yōu)化思路,請跟貼。
項目是年前一個朋友做的,客戶也是我的一個朋友,所以現(xiàn)在來幫忙優(yōu)化,系統(tǒng)很簡單,就是一個菜單頁面,客戶下單,然后打印機出小票,整個系統(tǒng)使用yii2基礎版 + MySQL5.6.29驅(qū)動。
客戶店里每天大約走1.5-2w的流水,現(xiàn)在最大的表有26w數(shù)據(jù),我切圖大家先看下。
從圖例看可能要優(yōu)化的地方
表引擎使用了MyISAM問題
order、order_box數(shù)據(jù)表瓶頸問題
我使用的工具本地環(huán)境MAMP
yii2-debug 神器小強
yii2的各種緩存
優(yōu)化原則代碼的修改最小化,盡量不動核心代碼以防止引入bug,最后在進行數(shù)據(jù)庫和服務器的優(yōu)化。
那咱就開始吧~
客戶說后臺登陸慢當我第一次聽客戶這樣說的時候,就已經(jīng)知道慢的絕對不是登陸,這個系統(tǒng)沒有權(quán)限、沒有很多日志、沒有登陸后的事件、僅僅就是一個登陸而已。
那很可能就是慢在登陸后進入的第一個頁面而給客戶的感覺是登陸慢。
那就看看這個頁面
頁面邏輯很簡單,就是一個銷售圖表,每天的銷售額曲線,那么問題最可能出現(xiàn)在這個圖表上,畢竟銷售額的計算看代碼都是從訂單實時分析出來的。
用yii2-debug看一看
果不其然,yii2-debug告訴我此action整個響應時間為2.652秒,而數(shù)據(jù)庫就用了2.518秒,查詢次數(shù)39次...
看看每個查詢,每一天執(zhí)行一個SQL語句,每個都用了90毫秒左右,畢竟是26w數(shù)據(jù)中拿數(shù)據(jù)。
似乎問題明朗了,解決這個數(shù)據(jù)庫查詢就解決了這個頁面,先看看這個圖表的代碼實現(xiàn)
$y = date("Y",time()); //年 $m = date("m",time()); //月 $days_num = date("t",time()); //當月天數(shù) $days = ""; $moneys = ""; for($i=1; $i<=$days_num; $i++){ $days .= $i.","; $begin_time = strtotime($y."-".$m."-".$i) + Yii::$app->params["business_hour"]["begin_time"]; $end_time = strtotime($y."-".$m."-".$i) + Yii::$app->params["business_hour"]["end_time"]; $money = Order::find() ->where([">","dish_id",0]) ->andWhere(["pay_state"=>"pay"]) ->andWhere([">=","pay_time",$begin_time]) ->andWhere(["<=","pay_time",$end_time]) ->andWhere(["store_id"=>Yii::$app->admin->identity->store_id]) ->sum("money"); $moneys .= ($money > 0 ? $money : 0).","; }
優(yōu)化的步驟很簡單:首先看能不能減少查詢次數(shù),如果不能就加速查詢,如果還不能就緩存結(jié)果。
在這段代碼中,無論今日是幾號,都進行了整月天數(shù)的查詢,我先來去掉不該進行的查詢。
修改及其簡單,只是增加了3行代碼
for($i=1; $i<=$days_num; $i++){ $days .= $i.","; if($i > date("d",time())){ $moneys .= "0,"; continue; } ........ }
但是通過減少不必要的查詢的結(jié)果是
數(shù)據(jù)庫檢索從39減少到30次,耗時從2.518秒減少到1.982秒。
對于加速查詢無外乎表類型選擇及索引的添加,本著表是所有action的表,蒼老師是世界的蒼老師,我先不動,只是記錄下dish_id、pay_state、pay_time、store_id四個字段,后面對order表進行改造的時候再考慮他們。
然后對于這種統(tǒng)計類數(shù)據(jù),沒有必要每次都實時讀取,我應該加一個緩存。
加個文件類型緩存如果你不會玩Yii2緩存,請移步到 Yii2緩存系列 先學習。
看這個圖表和當下代碼,我的緩存可以按照月份來,但是還要保證當天銷量的實時性,所以我緩存的是本月今天之前的數(shù)據(jù)。
首先去配置文件 config/web.php 設置
// conf/web.php ... "cache" => [ "class" => "yiicachingFileCache", ], ...
采用默認的就好,代碼進行一點小手術(shù)(將今天之前的代碼多帶帶處理),核心邏輯不變。
$cache = Yii::$app->cache; $cacheKey = "month-report-{$m}"; $days = ""; $moneys = ""; // 今天之前的數(shù)據(jù),也是我們要緩存的數(shù)據(jù) $monthDatBeforeToday = $cache->get($cacheKey); if ($monthDatBeforeToday === false) { for($i = 1;$i < date("d",time());$i++){ $days .= $i.","; $begin_time = strtotime($y."-".$m."-".$i) + Yii::$app->params["business_hour"]["begin_time"]; $end_time = strtotime($y."-".$m."-".$i) + Yii::$app->params["business_hour"]["end_time"]; $money = Order::find() ->where([">","dish_id",0]) ->andWhere(["pay_state"=>"pay"]) ->andWhere([">=","pay_time",$begin_time]) ->andWhere(["<=","pay_time",$end_time]) ->andWhere(["store_id"=>Yii::$app->admin->identity->store_id]) ->sum("money"); $moneys .= ($money > 0 ? $money : 0).","; } $monthDatBeforeToday = ["days"=>$days,"moneys"=>$moneys]; $cache->set($cacheKey,$monthDatBeforeToday,7200); } $days = $monthDatBeforeToday["days"]; $moneys = $monthDatBeforeToday["moneys"]; for($i=date("d",time());$i<=$days_num; $i++){ $days .= $i.","; if($i > date("d",time())){ $moneys .= "0,"; continue; } $begin_time = strtotime($y."-".$m."-".$i) + Yii::$app->params["business_hour"]["begin_time"]; $end_time = strtotime($y."-".$m."-".$i) + Yii::$app->params["business_hour"]["end_time"]; $money = Order::find() ->where([">","dish_id",0]) ->andWhere(["pay_state"=>"pay"]) ->andWhere([">=","pay_time",$begin_time]) ->andWhere(["<=","pay_time",$end_time]) ->andWhere(["store_id"=>Yii::$app->admin->identity->store_id]) ->sum("money"); $moneys .= ($money > 0 ? $money : 0).","; }
當然,從編寫上講,這段代碼可以繼續(xù)優(yōu)化,但是在原理上已經(jīng)完成了,我將今天之前的數(shù)據(jù)都緩存下來,今天的實時讀取,這樣就滿足了這個圖表和原來一樣的結(jié)果,為防止其他地方對訂單的修改,換成我2個小時更新一次。
用yii2-debug看看結(jié)果。
你沒看錯數(shù)據(jù)庫從39次到10次,耗時從2.518秒到0.1秒
Action執(zhí)行從2.652秒減少到0.212秒
初步使用我們Yii2優(yōu)化三原則中的兩條,Action執(zhí)行提高了12倍、數(shù)據(jù)庫耗時減少了23倍。
優(yōu)化的步驟很簡單:首先看能不能減少查詢次數(shù),如果不能就加速查詢,如果還不能就緩存結(jié)果。
記住它,一點點來,萬物均可優(yōu)化。
還有很多這僅僅是對統(tǒng)計數(shù)據(jù)采用緩存小試牛刀,如果對于訂單列表這種檢索那就要用到第二條原則了(如何讓查詢語句更快)。
下一篇將為你講解 對一個26萬數(shù)據(jù)的MYSQL表Yii2程序優(yōu)化實戰(zhàn)(真實例子)之二 【開刀數(shù)據(jù)表】
(完)
本文原創(chuàng)發(fā)布于微信公眾號 北哥小報 , 嚴謹?shù)脑瓌?chuàng)技術(shù)文,還有一些其他研究。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/61866.html
閱讀 3307·2023-04-26 00:57
閱讀 620·2021-10-08 10:05
閱讀 1367·2021-09-08 09:36
閱讀 4190·2021-08-12 13:31
閱讀 2557·2019-08-30 15:55
閱讀 2251·2019-08-30 15:55
閱讀 1026·2019-08-30 15:55
閱讀 2697·2019-08-29 13:17