一次顯著的效能提升,從8s到0.7s
來源:蘇三說技術
前言
最近我在公司最佳化了一些慢查詢SQL,積累了一些SQL調優
的實戰經驗。
我之前寫過一些SQL最佳化相關的文章《聊聊SQL最佳化的15個小技巧》和《explain | 索引最佳化的這把絕世好劍,你真的會用嗎?》,在全網廣受好評。
這篇文章從實戰的角度出發,給大家分享一下如何做SQL調優。
經過兩次最佳化之後,慢SQL的效能顯著提升了,耗時從8s
最佳化到了0.7s
。
現在拿出來給大家分享一下,希望對你會有所幫助。
1 案發現場
前幾天,我收到了一封報警郵件,提示有一條慢查詢SQL。
我開啟郵件檢視了詳情,那條SQL大概是這樣的:
SELECT count(*)
FROM spu s1
WHERE EXISTS (
SELECT *
FROM sku s2
INNER JOIN mall_sku s3 ON s3.sku_id = s2.id
WHERE s2.spu_id = s1.id
AND s2.status = 1
AND NOT EXISTS (
SELECT *
FROM supplier_sku s4
WHERE s4.mall_sku_id = s3.id
AND s4.supplier_id = 123456789
AND s4.status = 1
)
)
這條SQL的含義是統計id=123456789的供應商,未釋出的spu數量是多少。
這條SQL的耗時竟然達標了8s
,必須要做最佳化了。
我首先使用explain
關鍵字查詢該SQL的執行計劃
,發現spu表走了type型別的索引,而sku、mall_sku、supplier_sku表都走了ref型別的索引。
也就是說,這4張表都走了索引
。
不是簡單的增加索引,就能解決的事情。
那麼,接下來該如何最佳化呢?
2 第一次最佳化
這條SQL語句,其中兩個exists
關鍵字引起了我的注意。
一個exists
是為了查詢存在某些滿足條件的商品,另一個not exists
是為了查詢出不存在某些商品。
這個SQL是另外一位已離職的同事寫的。
不清楚spu表和sku表為什麼不用join,而用了exists。
我猜測可能是為了只返回spu表的資料,做的一種處理。如果join了sku表,則可能會查出重複的資料,需要做去重處理。
從目前看,這種寫效能有瓶頸。
因此,我做出了第一次最佳化。
使用join
+ group by
組合,將sql最佳化如下:
SELECT count(*) FROM
(
select s2.spu_id from spu s1
inner join from sku s2
inner join mall_sku s3 on s3.sku_id=s2.id
where s2.spu_id=s1.id ans s2.status=1
and not exists
(
select * from supplier_sku s4
where s4.mall_sku_id=s3.id
and s4.supplier_id=...
)
group by s2.spu_id
) a
文章中有些相同的條件省略了,由於spu_id在sku表中是增加了索引的,因此group by的效能其實是挺快的。
這樣最佳化之後,sql的執行時間變成了2.5s
。
效能提升了3倍多,但是還是不夠快,還需要做進一步最佳化。
3 第二次最佳化
還有一個not exists可以最佳化一下。
如果是小表驅動大表的時候,使用not exists確實可以提升效能。
但如果是大表驅動小表的時候,使用not exists可能有點弄巧成拙。
這裡exists右邊的sql的含義是查詢某供應商的商品資料,而目前我們平臺一個供應商的商品並不多。
於是,我將not exists改成了not in。
sql最佳化如下:
SELECT count(*) FROM
(
select s2.spu_id from spu s1
inner join from sku s2
inner join mall_sku s3 on s3.sku_id=s2.id
where s2.spu_id=s1.id ans s2.status=1
and s3.id not IN
(
select s4.mall_sku_id
from supplier_sku s4
where s4.mall_sku_id=s3.id
and s4.supplier_id=...
)
group by s2.spu_id
) a
這樣最佳化之後,該sql的執行時間下降到了0.7s。
之後,我再用explain關鍵字查詢該SQL的執行計劃。
發現spu表走了全表掃描,sku表走了eq_ref型別的索引,而mall_sku和supplier_sku表走了ref型別的索引。
可以看出,有時候sql語句走了4個索引,效能未必比走了3個索引好。
多張表join的時候,其中一張表走了全表掃描,說不定整個SQL語句的效能會更好,我們一定要多測試。
說實話,SQL調優是一個比較複雜的問題,需要考慮的因素有很多,有可能需要多次最佳化才能滿足要求。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70027826/viewspace-2998122/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- VS Code Java 最新更新!效能顯著提升!Java
- 我國數字政府服務效能顯著提升
- 重新架構:從 Redis 到 SQLite 效能提升架構RedisSQLite
- 垃圾回收機制GC從JDK 8到JDK 17的效能提升 - kstefanjGCJDK
- 記一次提升18倍的效能優化優化
- 從一次效能優化看https的效能優化HTTP
- Ross、何愷明等人提出PointRend:渲染思路做影像分割,顯著提升Mask R-CNN效能ROSCNN
- DenseMamba:大模型的DenseNet時刻,Mamba和RetNet精度顯著提升大模型SENet
- OpenKruise v1.3:新增自定義 Pod Probe 探針能力與大規模叢集效能顯著提升UI
- Omdia:2021年中國AMOLED產能將顯著提升
- 從提升樹到 XGBoost, 原理簡介
- 最新蘋果資訊:蘋果手錶6健康功能顯著提升蘋果
- 大資料技能立異才能顯著提升使用場景日益多元大資料
- 15億紅包開啟後,支付寶DAU和新增提升顯著
- SQL Server中使用Check約束達到提升效能SQLServer
- 用大模型最佳化大模型預訓練資料,節省20倍計算量,實現顯著效能提升!大模型
- apple watch series 6新功能|蘋果手錶6健康功能顯著提升APP蘋果
- 從第一次量產學到的東西
- 從一次外賣到對oauth2.0的思考OAuth
- 記一次從刪庫到恢復的經歷
- 從【預編譯】到【宣告提升】到【作用域鏈】再到【閉包】編譯
- 改變LoRA的初始化方式,北大新方法PiSSA顯著提升微調效果
- AMD RX590和RX580顯示卡效能對比 RX590顯示卡效能提升了多少
- 從一次翻車現場到GCD的原始碼分析GC原始碼
- 電腦雙顯示卡交火效能提升多少,雙顯示卡交火是什麼意思?
- 李航等提出多粒度AMBERT模型,CLUE、GLUE上優於BERT,中文提升顯著模型
- 應屆生-從想混著過到真正的熱愛程式設計程式設計
- 一場提升筆記本效能的變革 顯示卡塢的昨天今天和明天筆記
- 介面效能提升方法
- .NET MAUI 效能提升UI
- javascript效能提升之路JavaScript
- 如何提升JSON.stringify的效能?JSON
- 如何提升JSON.stringify()的效能?JSON
- Analyze table對Oracle效能的提升Oracle
- Java中的集合框架深度解析:從ArrayList到ConcurrentHashMap的效能考量Java框架HashMap
- 阿里提出結構保持的AI視覺演算法:顯著提升HDR影像轉LDR影像質量阿里AI視覺演算法
- Autolist:新研究結果顯示油價可能沒有顯著地影響到消費者的情緒
- 如何從請求、傳輸、渲染3個方面提升Web前端效能Web前端