首页 > 解决方案 > 提高前 1 个查询的性能

问题描述

我正在运行一批语句,以及此查询使用的相对时间的 100%:

select c.*,q.dbupddate
  into #c
  from 
   customer c
   cross apply
   (
    select top 1 code,transferred,dbupddate
    from transfer_customer_connect_log l
    where l.code=c.code
    order by dbupddate desc
   )q
  where q.transferred=0

有了这个计划:https ://www.brentozar.com/pastetheplan/?id=Syq811nJm

此查询旨在将行从一个数据库 (app_connect) 传输到另一个数据库 (app)。在表 transfer_customer_connect_log 中,transfer=1 的记录已经被处理并且必须被忽略。此外,从 transfer=0 的其余行中,某些(客户)代码可能在表中多次存在,具有不同的(dbupd)日期,在这种情况下,我必须只考虑最近的。

我从计划中看到sort by dbupddate,要制作前 1 部分,需要 97% 的时间。所以,我在 (dbupddate,code) 上添加了一个 pk 聚集索引。有趣的是,什么都没有改变!索引不会使排序变得不必要吗?

一种替代方法是,不是每次都进行前 1 个最近的检查,而是通过用标志标记“旧”行(已转移 = 0 但不是最近的前 1)来“保存”每次插入行的结果,并且然后在 a 中使用该标志将where其排除在将来的考虑之外。

这种思维方式靠谱吗?根据我描述的功能,我还能做些什么来改进这一点?

标签: sql-serverperformancetsqlcross-apply

解决方案


使用 row_number()

select * 
from ( select c.*, l.dbupddate, l.transferred 
            , row_number() over (PARTITION BY l.code ORDER BY l.dbupddate desc) as rn
        from customer c
        join transfer_customer_connect_log l
          on l.code = c.code 
     ) t
where t.rn = 1
  and t.transferred = 0

推荐阅读