[英]Need suggestions to further optimize this SQL Server query
我寫了這個非常簡單的查詢,它現在已經運行了 16 多個小時。 我已經嘗試了所有方法來優化它,但不知道如何進一步改進它。 請幫忙。
select
a.*, b.TM_IN_XIT
into
scratch.dbo.ab_peak2
from
scratch.dbo.ab_peak1 a
left join
Scratch.dbo.ab_tnt b on a.DC_ZIP between b.ORIG_ZIP_low
and b.ORIG_ZIP_high
and a.Destination between b.DEST_ZIP_low and b.DEST_ZIP_high
and a.Carr_Mode = b.Mode;
表scratch.dbo.ab_peak1
如下所示,有大約 700k 條記錄:
+-----------------------------------------------+
| ShipmentNumber DC_ZIP Destination Carr_Mode |
+-----------------------------------------------+
| 252838748 60622 10016 A |
| 252731857 60622 40517 A |
| 252685087 60622 91601 B |
| 252574905 60622 7017 B |
| 252877256 60622 97230 A |
| 254791362 20166 54971 B |
| 255866277 60622 19131 A |
| 255728088 60622 27713 B |
| 255614555 60622 10009 A |
| 255823071 60622 33556 B |
+-----------------------------------------------+
表Scratch.dbo.ab_tnt
如下所示,有大約 150 萬條記錄:
+-----------------------------------------------------------------------------------+
| Mode ORIG_ZIP_low ORIG_ZIP_high DEST_ZIP_low DEST_ZIP_high TM_IN_XIT |
+-----------------------------------------------------------------------------------+
| A 41042 41042 62556 62556 2 |
| B 41042 41042 62556 62556 3 |
| A 41042 41042 62557 62557 1 |
| B 41042 41042 62557 62557 2 |
| A 41042 41042 62558 62563 2 |
| B 41042 41042 62558 62563 3 |
| A 41042 41042 62565 62567 1 |
| B 41042 41042 62565 62567 2 |
| A 41042 41042 62568 62570 2 |
| B 41042 41042 62568 62570 3 |
+-----------------------------------------------------------------------------------+
我想要實現的目標 - “a”是一個 Shipments 表,而“b”是一個表,其中包含所有出發地-目的地組合的運輸時間。 “b”表的結構基於 zip 范圍,如上所示。 我試圖通過在“b”表中查找來為“a”表的每批貨物引入運輸時間。
我已經嘗試過以下操作:
還有其他建議嗎?
對於此查詢:
select a.*, b.TM_IN_XIT
into scratch.dbo.ab_peak2
from scratch.dbo.ab_peak1 a left join
Scratch.dbo.ab_tnt b
on a.DC_ZIP between b.ORIG_ZIP_low and b.ORIG_ZIP_high and
a.Destination between b.DEST_ZIP_low and b.DEST_ZIP_high and
a.Carr_Mode = b.Mode;
您首先想嘗試索引。 顯而易見的嘗試是ab_tnt(mode, orig_zip_low, orig_zip_high, dest_zip_low, dest_zip_high, tm_in_xit)
。
我也可能傾向於這樣寫查詢:
select a.*,
(case when a.DC_ZIP <= b.ORIG_ZIP_high and a.destination <= b.DESC_ZIP_high
then b.TM_IN_XIT
end) as TM_IN_XIT
into scratch.dbo.ab_peak2
from scratch.dbo.ab_peak1 a outer apply
(select top 1 b.*
from Scratch.dbo.ab_tnt b
where a.DC_ZIP >= b.ORIG_ZIP_low and
a.Destination >= b.DEST_ZIP_low and
a.Carr_Mode = b.Mode
order by b.ORIG_ZIP_low, b.DEST_ZIP_low
) b;
現在,這不是完全相同的查詢。 它返回第一個可能匹配的郵政編碼。 這個想法是子查詢可能會適當地使用ab_tnt(mode, b.ORIG_ZIP_low, b.DEST_ZIP_low)
上的索引。
然后case
語句確定是否真的匹配。
我在一個維度上非常成功地使用了這個邏輯(例如處理 IP 范圍)。 我沒有將它用於二維,但是如果您當前的查詢已經運行了一天的大部分時間,那么值得嘗試。
注意:您可以使用(select top 1000 * from scratch.dbo.ab_peak1) a
而不是表,通過在記錄子集上運行來測試性能。
只是一個想法,但您是否嘗試過枚舉ab_tnt
所有可能組合,並使用結果加入ab_peak1
? 這是一個使用公共表表達式的示例,但臨時表可能會更好。 此外,此答案假定您有一個Integers
表。
;with dest as (
select dest_zip = i.I, tnt.Mode, orig_zip_low, orig_zip_high, tm_in_xit
from Integers i
join ab_tnt tnt on i.I between tnt.dest_zip_low and tnt.dest_zip_high
)
, tnt as (
select dest.Mode, dest_zip, orig_zip = i.I, dest.tm_in_xit
from Integers i
join dest on i.I between dest.orig_zip_low and dest.orig_zip_high
)
select *
from ab_peak1
join tnt
on ab_peak1.DC_ZIP = tnt.orig_zip
and ab_peak1.Destination = tnt.dest_zip
and ab_peak1.Carr_Mode = tnt.Mode
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.