Exists的妙用,大幅度提高查詢速度

2021-05-23 18:56:44 字數 2654 閱讀 2792

這段時間碰到乙個模組,sql查詢特別的慢,一直在努力想辦法優化它。

問題的**,這是乙個生產加工的模組存在的問題,

主從記錄。

主表主要字段:狀態(未複核=0,複核=1,生產完成=3),id,主表記錄生產時間,客戶名稱,要求交貨日,下單人,下單時間等等,

從表主要字段:貨品編號,貨品名稱,生產數量,領料數量,主記錄id等等。

客戶的需求: 客戶要求主記錄狀態,僅顯示(未複核=0,複核=1,生產完成=3)是不夠的要把,(全部領料,部分領料,未領料)這些狀態都新增進來,並且可以查詢,在主記錄的grid中顯示出來。

解決方案:

(一)修改程式設計滿足客戶要求

原先設計程式的時候沒有考慮要把(領料總數和貨品生產總數)在主表記錄中記錄進去,如果但是記錄進去的話,現在做上面那個狀態就比較容易啦。現在要改程式是比較麻煩的,而且還有老資料調整的問題,已及程式上,修改,刪除從表記錄同步主記錄領料總數,生產總數的問題,基於這個考慮修改程式設計暫不考慮。

(二)通過改變查詢sql來達到這個效果。

sql思路1: sql 這邊的話,剛開始採用的是比較正統的思路:

1.將從表領料數量,生產數量資料安mainid分組做sum統計 作為字表c;

2.主表記錄去left join 字表c。

具體sql如下:

select c.總領料數量,c.總生產數量,a.* from 主表名稱 a 

left join (

select sum(nvl(領料數量,0)) as 總領料數量,sum(生產數量)as 總生產數量,

fywdh  

from 從表名稱  group by 從表mainid

) c   

on a.id=c.mainid 

這樣的話有了c.sl,c.yrksl就可以實現剛才那個狀態啦,

做乙個calcstate

如果主表mainstate = 0 ;value='未複核';

如果主表mainstate = 1 ;value='複核';

如果主表 總領料數量 < 總生產數量 ;value='部分領料';

如果主表 總領料數量 = 總生產數量 ;value='全部領料領料';

如果主表mainstate = 3 ;value='生產完成';

查詢也是很好做的: 按照上面來就可以啦。

這樣子如果從完成任務的角度看是已經好,但是實際程式執行起來,效果卻是很不理想,

原因就是這個left join一做,以前查詢速度是1秒,現在變成30秒以上,那還是網速好的時候。

客戶這個時候又提要求啦,這個生產加工模組實在是太慢啦,(我自己都覺得慢,汗啊!)

基於這個原因,我翻看相關的sql書籍,通過很多嘗試,將這段sql優化了下,

成功的將查詢速度從30縮減到5秒一下。那到底是如何做的呢?

預知正解 ,請看sql思路2。

sql思路2:

仔細分析客戶的需求,客戶要的僅僅是乙個領料狀態的顯示,和查詢,那我們滿足這個就可以;

基於這個考慮,總領料數量,總生產數量是不是可以不用在主表記錄中顯示出來,

在主的記錄中直接顯示領料狀態就可以啦。

思路有啦

著手改sql

sql中有個exists可以過濾資料,以前都是用在where 後面用的,我想是不是可以放在

case when then else end 

這個裡面的when後面呢,如果可以這樣的話,

我是不是就可以直接的 出它的狀態來。

經過一番努力結果是欣慰的:

sql如下:

select

case when not exists (

select c.id from tuser_hpcb c

where c.main  = a.frwdh 

and nvl(c.fsl, 0) >  nvl(c.fyrksl, 0))

then ''全部領料'' '

when not exists (select c.id from 生產加工從表 c

where c.fywdh = a.frwdh '

and nvl(c.fflag, 0) <> 4

and nvl(c.fyrksl, 0)> 0)

then ''未領料'' '

else   ''部分領料''

end as ''領料狀態'', a.* from 生產主表 a '

where  再加上查詢條件。

其中select c.id from 生產加工從表 c  這塊也是要注意的,千萬不要寫成

select c.* from 生產加工從表 c 這樣的話,速度上會變慢很多,sql執行後所要空間也會增加,

同時因為c.id是有做索引的,速度也會加快,關鍵是不需要顯示那麼些,

我們這裡僅僅是要有個字段而已。

上面那段這段做好後,calcstate

value=dataset['領料狀態']

如果主表mainstate = 0 ;value='未複核';

如果主表mainstate = 1 ;value='複核';

如果主表mainstate = 3 ;value='生產完成';

這樣就好了,當然狀態查詢的sql也是要改改的;不過我想這裡就不需要我再提啦 

直接在where用上exists

,就可以悉數解決問題。

MySQL基礎 大幅度提高效能方案,分割槽表

下面就筆者工作中遇到的時間問題,模擬一下情況對大家進行介紹.工作中仍然是海量資料出現的情況.每年大概會有幾億條記錄.而且資料的時效性比較強.但歷史資料仍然要求保留.這個時候經過分析和研究,最終決定通過時間字段進行分割槽.下面是分割槽表的建立 讀者門在插入了不同年份時間段以後,可以時間欄位為條件進行查...

MySQL基礎 大幅度提高效能方案,分割槽表

下面就筆者工作中遇到的時間問題,模擬一下情況對大家進行介紹.工作中仍然是海量資料出現的情況.每年大概會有幾億條記錄.而且資料的時效性比較強.但歷史資料仍然要求保留.這個時候經過分析和研究,最終決定通過時間字段進行分割槽.下面是分割槽表的建立 讀者門在插入了不同年份時間段以後,可以時間欄位為條件進行查...

大幅度增加和改良了input元素的種類

對於不支援新增input元素的瀏覽器來說,統一將這些input元素視為text型別 是一種專門用來輸入url位址的文字框,提交的時候如果這個文字框的內容不是url地質格式的文字,則不允許提交 專門用來輸入email位址的文字框,提交的時候如果該文字框中的內容不是email位址格式的文字則不允許提交,...