加快交叉应用查询

Posted

技术标签:

【中文标题】加快交叉应用查询【英文标题】:Speed up Cross Apply query 【发布时间】:2016-03-18 12:34:24 【问题描述】:

我有一个使用交叉应用的查询。我需要对多个 [Quote Id] 运行查询。这是我的原始查询:

SELECT distinct
       [Reports].[Quote_Header_Details_vw].[Quote_Id]    
      ,[Reports].[Quote_Header_Details_vw].[Quote_Created]
      ,[Reports].[Quote_Header_Details_vw].[Com_Product]
      ,[Reports].[Quote_Header_Details_vw].[Ene_Product]
      ,b.[Completed]
      ,b.[Description]
FROM [Reports].[Quote_Header_Details_vw]
   CROSS APPLY (SELECT Top 1
                         Core.Job.[Completed]
                        ,Core.Job.[Description]
FROM Core.Job
WHERE [Quote_Header_Details_vw].[Quote_Created]>=Core.Job.[Completed] 
And Core.Job.[Description] like '%'+[Reports].[Quote_Header_Details_vw].[Ene_Product]
Order by Core.Job.[Completed] DESC) AS b

我了解在 Cross Apply 语句中执行 Top 1 操作需要花费大量时间。查询当前运行单个报价 ID 需要 40 多秒,并且随着 Core.Job 表的增长,查询将变得越来越慢。因此,这对我来说不是一个可行的解决方案。

有没有更快更好的方法来做到这一点?非常感谢你。请注意 [Quote_Header_Details_vw] 和 [Core.Job] 表之间没有关系,即不能加入它们。

【问题讨论】:

CROSS APPLY performance difference的可能重复 @a_horse_with_no_name 知道了,谢谢。 @Ashraf Abusada 谢谢。不一样,两张表完全没有关联。 您是否调整了这 2 个查询中的每一个?使用 Sql Server Profiler 查看是否可以先执行此操作,如果优化(良好的索引等)然后查看CROSS APPLY 您的过滤器“Core.Job.[Description] like '%'+[Reports].[Quote_Header_Details_vw].[Ene_Product]”是不可搜索的,将对每条记录进行全表扫描只返回一行。 【参考方案1】:

只需将它们放在变量中,然后在选择中使用该变量

declare @dd1 varchar(20);
declare @dd2 varchar(20);
select top (1) @dd1 = [name],  @dd2 = [dispName]
from [table]
order by [name] desc; 
select @dd1, @dd2;

OP 需要的细节

declare @dd1 varchar(20);
declare @dd2 varchar(20);

SELECT Top (1)
       @dd1 = Core.Job.[Completed]
     , @dd2 = Core.Job.[Description]
FROM Core.Job
WHERE [Quote_Header_Details_vw].[Quote_Created] >= Core.Job.[Completed] 
And Core.Job.[Description] like '%'+[Reports].[Quote_Header_Details_vw].[Ene_Product]
Order by Core.Job.[Completed] DESC;


SELECT distinct
       [Reports].[Quote_Header_Details_vw].[Quote_Id]    
      ,[Reports].[Quote_Header_Details_vw].[Quote_Created]
      ,[Reports].[Quote_Header_Details_vw].[Com_Product]
      ,[Reports].[Quote_Header_Details_vw].[Ene_Product]
      ,@dd1 as [Completed]
      ,@dd2 as [Description]
FROM [Reports].[Quote_Header_Details_vw];

或者试试

select * from 
(
SELECT r.[Quote_Id]    
      ,r.[Quote_Created]
      ,r.[Com_Product]
      ,r.[Ene_Product]
      ,b.[Completed]
      ,b.[Description] 
      ,row_number() over (partition by r.[Quote_Id] order by b.[Completed] desc) as rn
FROM [Reports].[Quote_Header_Details_vw] r
join Core.Job b
       on r.[Quote_Created] >= b.Job.[Completed] 
      And b.[Description] like '%'+r.[Ene_Product]
) tt
where tt.rn = 1

【讨论】:

非常感谢。但我不明白这其中的逻辑。表 b 按 [Completed] DESC 排序,而不是按 [name] DESC 排序。我还需要将 [Quote_Created] 和 [Completed] 放入变量中吗? 将 CROSS APPLY 的输出放入变量中并消除交叉应用。这只是如何分配变量的示例语法。 这不会给出正确的值 - 它们需要按行评估,因此适用。 @GarethLyons 你是对的。我将“请注意 [Quote_Header_Details_vw] 和 [Core.Job] 表之间没有关系”表示实际上没有关系。感谢您的反对票以加强这一点。 非常感谢你们。如果我的观点不够清楚,我深表歉意。对于 [Reports].[Quote_Header_Details_vw] 表中的每个 [Quote_Id],我想在表 b 中找到前 1 个 [Description]。为了创建 b,我应用了两个过滤器,它们使用来自每个 [Quote_Header_Details_vw].[Quote_Id] 的信息。这意味着,对于每个 [Quote_Id] 行,表 b 将是不同的。 @Paparazzi,我会按照你的逻辑进行测试。谢谢。

以上是关于加快交叉应用查询的主要内容,如果未能解决你的问题,请参考以下文章

交叉应用使用的子查询不返回结果

sccm 查询交叉应用 outerapply 不提供输出

使用交叉应用子查询优化 sql 查询的问题

SQL Unpivot、交叉应用、动态查询?

优化具有 While 循环和交叉应用的 T-SQL 查询

SQL Server 交叉应用