SQL優(yōu)化

等價(jià)替換left join / right join查詢

多表的left join / right join關(guān)聯(lián)查詢性能較低,可以考慮等價(jià)替換為join的SQL語(yǔ)句或者是用逗號(hào)分隔各個(gè)表,然后用where條件替代on條件作為關(guān)聯(lián)條件的方式,關(guān)聯(lián)查詢多表(目前也推薦用逗號(hào)分隔,where條件替代on條件的方式進(jìn)行多表內(nèi)連接查詢)。

例如對(duì)于同時(shí)符合以下設(shè)定的場(chǎng)景下:

  1. 如果A表為主表,B為從表。
  2. 其中,出參包含AB兩個(gè)表的數(shù)據(jù),查詢的條件可能來(lái)源于A,B表。
  3. A表有記錄,B表未必有記錄。
  4. B表的code字段與A表的主鍵id字段關(guān)聯(lián)。
  5. 各個(gè)查詢條件之間是AND關(guān)系。

那么,查詢SQL語(yǔ)句最直觀地會(huì)寫(xiě)為:

select A.id, B.id from A left join B on A.id=B.code where ……

但是這樣的SQL語(yǔ)句在寬表引擎下并非性能最佳, 可以等價(jià)替換為如下:

  1. 如果查詢條件來(lái)源于A和B兩表,并且查詢條件都是AND邏輯拼接。可以改為:
select A.id, B.id from A, B where A.id=B.code and ……
  1. 如果查詢條件只來(lái)源于A表,可改為使用以下的兩條SQL:
select A.id from A where ……

將以上查詢獲取得到的A表的id傳入到下列B表的SQL,查詢獲取B表的出參。

select B.id from B where B.code=?
  1. 如果查詢條件只來(lái)源于B表,可以改為使用以下的兩條SQL:
select B.id, B.code from B where ……

將以上查詢獲取得到的B表的code傳入到下列A表的SQL,查詢獲取A表的出參。

select A.id from A where A.id=?

count查詢不應(yīng)該帶order by

count查詢的目的是為了返回符合條件的總記錄數(shù),但是order by則是對(duì)符合條件的記錄進(jìn)行排序,查詢總數(shù)無(wú)需排序,排序則會(huì)增加非必要的耗時(shí),應(yīng)該在count查詢語(yǔ)句中刪除order by


結(jié)合實(shí)際業(yè)務(wù)場(chǎng)景考慮是否在查詢SQL中帶有order by,count

如果模型中滿足某條件的數(shù)據(jù)量很大,查詢的SQL語(yǔ)句中帶有order by,count過(guò)程非常緩慢??山Y(jié)合自身業(yè)務(wù)場(chǎng)景考慮是否可以放棄。

如果業(yè)務(wù)上的 order by,count 不能刪除,可以通過(guò)以下的方案進(jìn)行優(yōu)化:

涉及count的優(yōu)化
由于count查詢嚴(yán)重影響查詢體驗(yàn),所以可以考慮分情況討論是否需要查詢count。count一般用于前端分頁(yè)展示選擇頁(yè)數(shù),來(lái)進(jìn)行分頁(yè)選擇查詢。count查詢的優(yōu)化方案,將腳本查詢接口的count輸出改為可選輸出,然后通過(guò)入?yún)⒖刂剖欠褫敵?,如果需要輸出再查?code>count,否則不返回count。

a. 對(duì)于頁(yè)面上調(diào)用腳本的查詢接口時(shí),先試探查詢傳入start=5000,limit=5001,首次查詢先通過(guò)入?yún)⒖刂撇徊樵?code>count并且攜帶其他查詢條件,如果返回記錄不為空,則表示滿足條件的記錄大于5000條。
b. 如果能查出一條記錄則表示記錄超過(guò)5000,則后續(xù)的正常分頁(yè)查詢也不查詢count,只將分頁(yè)查詢的返回分頁(yè)數(shù)據(jù)展示到頁(yè)面上,頁(yè)面也不展示count。頁(yè)面也只可以翻頁(yè)到0~5000的記錄,5000以上的無(wú)法看。
c. 如果查不到記錄(表示滿足條件的數(shù)量少于5000)。則可以正常返回count,將返回的count用于前端分頁(yè)的總記錄數(shù)量,此時(shí)返回的分頁(yè)數(shù)據(jù)亦可以正常展示,用法與普通的分頁(yè)查詢用法一致。


多表關(guān)聯(lián)不要使用select * 的方式返回對(duì)應(yīng)字段的記錄

由于多表關(guān)聯(lián)字段的數(shù)量較多,如果是select *,可能會(huì)返回很多不需要的字段記錄,導(dǎo)致增加了非必要的數(shù)據(jù)傳輸。建議不要使用select *,而是根據(jù)需要返回的字段一個(gè)個(gè)列出來(lái),例如只需要id就寫(xiě)為select id


非必要場(chǎng)景下,避免使用distinct關(guān)鍵字進(jìn)行記錄去重

如果確定了返回的記錄不會(huì)有重復(fù)的,應(yīng)該避免使用distinct關(guān)鍵字進(jìn)行去重,distinct關(guān)鍵字在并發(fā)情況下性能較差。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容