2019年9月5日10:02:34
本地調試
git https://github.com/barryvdh/laravel-debugbar
composer require barryvdh/laravel-debugbar --dev
APP_DEBUG TRUE
配置.env
本地調試很方便,千萬不要弄到線上去了,因為這個東西其實很消耗資源的
公司的項目,因為使用workerman做消息推送,我之前想是做主從,但是想到需要額外花費,而且目前大部分是內部使用,就開始了優化mysql之路
框架使用的是laravel5.7,基本都要求使用orm,但是框架里面還有有小部分使用的復雜使用的原生的,很多使用聯表,注意這里的聯表不是join聯表,因為性能差異
查詢使用的工具都是阿里雲提供的工具
阿里雲ApsaraDB診斷報告,SQL洞察分析,
ApsaraDB診斷報告對檢查慢查詢還是很有效的,很容易找到問題去優化
一個demo
SELECT * FROM `sale_out_storage` WHERE `shop_id` = ? AND `is_delete` = ? AND `storage_status` = ? AND NOT EXISTS ( SELECT * FROM `k3_sale_out_storage_task` WHERE `sale_out_storage`.`id` = `k3_sale_out_storage_task`.`sale_out_storage_id` AND `is_delete` = ? AND `is_cancel` = ? AND `status` IN (?) AND `shop_id` = ? ) AND EXISTS ( SELECT * FROM `sale_order` WHERE `sale_out_storage`.`sale_order_id` = `sale_order`.`id` AND `order_status` != ? ) AND `storage_date` > ? 建議 1. 返回記錄數 語句最大返回記錄數為55。
2. 行掃描 行掃描與行返回之比為178673。
3. 索引 該語句沒有使用聚合函數和模糊查詢,行掃描與行返回之比很高。創建合理索引會帶 來很大的優化空間
我發現的最大的問題有以下幾點:
1,where in的性能其實很差,經常需要大范圍掃描,減少in的范圍,或者使用exists代替
2,使用時間范圍查詢的時候一定要加上索引,不然效率很差,大范圍掃描行數
3,索引不能添加過多,過多也會導致性能下降,比如log日志表,提供給多方查詢的時候,添加過多,mysql內部多個索引進行查詢的時候,會增加計算量,大大消耗cpu
4,如果有多個索引比如訂單表,請注意一定優先最左原則,最大化利用索引,強調代碼規范
5,join 會大大增加內存消耗,即使在符合大表連小表的原則
6,適當添加索引,特別是在laravel with聯表的時候
$parent_sale_order_info = SaleOrder::where('shop_id', $shop_id)->where('is_delete', 10) ->with([ 'sale_order' => function ($query) { $query->where('is_delete', 10)->with([ 'sale_out_storage' => function ($query) { $query->where('is_delete', 10)->where('storage_status', 20)->with([ 'sale_out_storage_sku' => function ($query) { $query->where('is_delete', 10); } ]); }, 'sale_pay' => function ($query) { $query->where('is_delete', 10); } ]); }, 'sale_settle' => function ($query) { $query->where('is_delete', 10)->with([ 'sale_settle_sku' => function ($query) { $query->where('is_delete', 10); } ]); }, 'sale_pay_record' => function ($query) { $query->where('is_delete', 10)->where('status', 20); } ]) ->where('id', $parent_order_id) ->first();
優化完的結果
有日常80%-95%,優化完之后30%上下,阿里雲的rds mysql 5.7,2核4g
補充一點,核心的解決辦法就是找到出問題點在哪,我這個場景就是因為推送大大增加數據查詢消耗,導致mysql掃描行大大增加
解決思路如下:了解業務的繁忙點,找到頻繁的核心表,優先嘗試,優化索引,這樣的就不需要修改很多代碼,如果發現只優化索引不能解決,堅決修改代碼,並指導開發人員是為什么需要這樣寫
更改書寫習慣和理念,這樣才能根本解決問題,不然只是臨時救火。
一點參考的文章
https://www.cnblogs.com/ManyQian/p/9076247.html#_label2
https://www.cnblogs.com/ManyQian/p/9038063.html
https://www.cnblogs.com/ManyQian/p/9026606.html
https://www.cnblogs.com/zjxiang/p/9160810.html