前段時間,博主線上項目的幾個後端介面執行耗時達到了三、四秒鐘以上,查看介面代碼,發現 sql 語句執行過慢,於是開始分析 sql 執行 這裡把比較經典的優化案例分享給大家。 本文所講述 MySql 8.0+ 代碼演示地址:https://github.com/wayn111/newbee-mall- ...
前段時間,博主線上項目的幾個後端介面執行耗時達到了三、四秒鐘以上,查看介面代碼,發現 sql 語句執行過慢,於是開始分析 sql 執行 這裡把比較經典的優化案例分享給大家。
- 本文所講述 MySql 8.0+
- 代碼演示地址:https://github.com/wayn111/newbee-mall-pro
- 博主github地址:https://github.com/wayn111 歡迎大家關註,點個star
一、or 查詢條件錯誤
線上有一個第三方賬戶掃碼綁定手機號登錄的介面,這個介面正常邏輯如下:
- 使用 蘋果、QQ、微信獲取掃描客戶端登錄二維碼,獲取用戶第三方賬戶唯一ID後。
- 判斷第三方賬戶ID是否存在用戶表中,存在且已綁定手機號則直接返回用戶 token 進行登錄操作。
- 不存在則提示用戶進行綁定手機號操作。
- 用戶填寫手機號及簡訊驗證碼後,進行第三方賬戶唯一ID與手機號的綁定,成功則返回用戶 token 進行登錄操作。
博主記得這個介面是在21年10月上線的,到現在經歷了一年多,介面執行時間是越來越慢,初步分析是用戶數量持續增長,用戶表記錄越來越多,導致 sql 查詢執行效率越來越低導致。這裡用 vc_member_bak 進行舉例,表結構以及數據展示,其中 apple_id、weixn_id、qq_id 有建立索引:
vc_member_bak 表數據量在46萬左右,開啟日誌分析後,發現是下麵這條 sql 執行太慢導致:
SELECT * FROM vc_member
WHERE qq_id = 'xxx' OR app_id = 'xxx' OR weixin_id = 'xxx' ;
執行結果:
需要1.3秒左右,這是在我本地模擬的數據,線上用戶在百萬級別,耗時已經達到2、3秒,於是博主開始上 explain,分析 sql 執行:
由於 explain 結果中 key 列為空,明顯可知雖然 possible_keys 列有值,但是執行過程中,沒有使用索引導致全表查詢,從rows 列為46萬可以看出已經基本接近於全表查詢。
那麼問題出在哪裡?我們不是已經給 apple_id、weixn_id、qq_id 三個欄位都添加索引了嗎。
於是博主仔細查詢 sql 語句發現裡面有坑,查詢的 where 條件上使用的三個條件欄位是分別是 app_id、weixin_id、qq_id,而我們的索引欄位是 apple_id、weixn_id、qq_id,很明顯這是查詢欄位 apple_id 寫成 app_id 了導致。app_id 沒有加索引,所以在 or 條件查詢下執行的就是全表掃描。
更改欄位後執行結果:
Ok,這裡發現了是查詢欄位寫錯了,那麼修改查詢欄位正確後,查詢0.18秒就正常了。