等價(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)景下:
- 如果A表為主表将塑,B為從表脉顿。
- 其中,出參包含AB兩個(gè)表的數(shù)據(jù)点寥,查詢的條件可能來(lái)源于A艾疟,B表。
- A表有記錄敢辩,B表未必有記錄蔽莱。
- B表的code字段與A表的主鍵id字段關(guān)聯(lián)。
- 各個(gè)查詢條件之間是
AND
關(guān)系戚长。
那么盗冷,查詢SQL語(yǔ)句最直觀地會(huì)寫為:
select A.id, B.id from A left join B on A.id=B.code where ……
但是這樣的SQL語(yǔ)句在寬表引擎下并非性能最佳, 可以等價(jià)替換為如下:
- 如果查詢條件來(lái)源于A和B兩表同廉,并且查詢條件都是
AND
邏輯拼接仪糖。可以改為:
select A.id, B.id from A, B where A.id=B.code and ……
- 如果查詢條件只來(lái)源于A表迫肖,可改為使用以下的兩條SQL:
select A.id from A where ……
將以上查詢獲取得到的A表的id傳入到下列B表的SQL锅劝,查詢獲取B表的出參。
select B.id from B where B.code=?
- 如果查詢條件只來(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ò)程非常緩慢」卓耍可結(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就寫為select id
本谜。
非必要場(chǎng)景下初家,避免使用distinct關(guān)鍵字進(jìn)行記錄去重
如果確定了返回的記錄不會(huì)有重復(fù)的,應(yīng)該避免使用distinct
關(guān)鍵字進(jìn)行去重乌助,distinct
關(guān)鍵字在并發(fā)情況下性能較差溜在。