需要进一步优化此SQL Server查询的建议吗

需要进一步优化此SQL Server查询的建议吗,sql,sql-server,query-optimization,Sql,Sql Server,Query Optimization,我写了这个非常简单的查询,它已经运行了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

我写了这个非常简单的查询,它已经运行了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是一个发货表,b是一个包含所有始发地-目的地组合的中转时间的表。b表的结构基于zip范围,如上所示。我试图通过在b表中查找来为a表的每批货物带来运输时间

我已经试过了:

TNT表中保留的zipcodes>=PEAK1表中的minzipcodes和此查询的:

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_tntmode、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_tntmode、b.ORIG_ZIP_low、b.DEST_ZIP_low上的索引

然后,case语句确定是否存在匹配项

例如,我在一维处理IP范围时非常成功地使用了这种逻辑。我没有在二维中使用它,但是如果您当前的查询已经运行了一天的大部分时间,那么值得一试


注意:您可以通过使用select top 1000*from scratch.dbo.ab_peak1 a而不是表格来测试记录子集的性能。

只是一个想法,但是您是否尝试过枚举ab_tnt中所有可能的组合,并使用结果加入ab_peak1?下面是一个使用公共表表达式的示例,但是临时表可能工作得更好。此外,这个答案假设您有一个整数表


您可能有XY问题。请说明您正试图完成的任务:输入->预期输出验证您的查询执行计划。您可能希望引入一个数字表,以消除联接中的中间值。@MitchWheat-a是一个装运表,b是一个包含所有来源-目的地组合的运输时间的表。b表的结构基于zip范围,如上所示。我试图通过在b表中查找来为a表的每批货物带来运输时间。@Balde-我对执行计划不是很熟悉,你能帮我检查一下吗?我尝试了许多不同的索引,但都不起作用。SQL仍然使用表扫描。我强制使用索引,但没有改进。@Gordon-我尝试了你的建议,但没有得到预期的结果。第二个子查询中的条件对一组记录有效,但由于只保留了第一个子查询中的条件,它通常与第一个子查询中的条件不匹配。因此,我将_XIT中的大多数TM_作为空值。谢谢你的建议。我的查询在运行约37小时后完成。@Crypticlight。尽管该条件适用于许多记录,但我希望通过ORDERBY条件匹配where子句的第一个记录是匹配的记录。
;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