【问题标题】:Improve performance on top 1 query提高前 1 个查询的性能
【发布时间】:2018-11-09 00:51:08
【问题描述】:

我正在运行一批语句,并且该查询使用了 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 个最近的检查,而是通过用标志,然后在where 中使用该标志以将其排除在未来考虑之外。

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

【问题讨论】:

  • 您的索引应该首先按代码,然后按 dbupddate,因为您首先按客户代码过滤,然后获取日期。您也可以尝试使用 MAX() 进行分组。
  • ezlo 有效。我可能会尝试改进它,但现在它有一个索引搜索代码,前 n 需要 0 时间:)

标签: sql-server performance tsql cross-apply


【解决方案1】:

使用 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-08-03
    • 1970-01-01
    • 2021-08-03
    • 2013-02-17
    • 2021-12-15
    • 2014-04-09
    • 2013-01-16
    相关资源
    最近更新 更多