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