【问题标题】:SQL Sub-query run's very fast individually, but when used in select is very slowSQL 子查询单独运行非常快,但在 select 中使用时非常慢
【发布时间】:2018-10-03 18:41:33
【问题描述】:

我有一组表,我要加入这些表以创建一个记录集,然后在该集上运行一个额外的选择来检索一些记录。 代码中的查询在视图中用作 CTE。

仅检查子查询时,它的运行速度非常快,例如 0.01 - 0.02 秒。 如果使用临时表来检索记录,这同样适用。因为我打算在视图中使用它,所以临时表解决方案超出了范围。常规查询运行时间为 37-50 分钟。

SELECT 
 CallDate
,MediaChannel
,SubCategory
,Vendor
,BusinessVertical
,SUM(NumberOfLeads) AS NumberOfLeads
,CASE 
    WHEN SUM([CostPerLead]) <> 0
        THEN SUM([CostPerLead])
    ELSE NULL
    END AS Cost
,[CostPerLead]
,SourceName
,ParentLeadSource
,IsBillable
,dvce_type

FROM (
SELECT [PhoneLabel]
    ,[DialogTechCallId] = cd.DialogTechCallId
    ,[LeadId] = c.LeadId
    ,[CostPerLead] = CAST(cpl.cost AS INT)
    ,[SourceName] = bt.LeadCompany
    ,[ParentLeadSource] = ftlc.fruit
    ,[DialogTechPhoneNumber] = cd.CalledNumber
    ,[CallDate] = CAST(cd.[CallDateTime] AS DATE)
    ,[CallType] = cd.CallType
    ,[TalkTime] = cd.[TalkTimeMinutes]
    ,[TalkTimeSeconds] = CASE 
        WHEN ISNUMERIC(cd.[TalkTimeMinutes]) = 1
            THEN CAST(cd.[TalkTimeMinutes] AS DECIMAL(10, 2)) * 60
        ELSE 0
        END
    ,[TimeToQualify] = bt.Billabletime
    ,[IsBillable] = CASE 
        WHEN ISNUMERIC(cd.[TalkTimeMinutes]) = 1
            THEN CASE 
                    WHEN CAST(cd.[TalkTimeMinutes] AS DECIMAL(10, 2)) * 60 
    >= CAST(bt.Billabletime AS INT)
                        THEN 1
                    WHEN bt.Billabletime = 900
                        THEN 1
                    ELSE 0
                    END
        ELSE 0
        END
    ,[MediaChannel] = ftlc.channel2
    ,[SubCategory] = ftlc.sub
    ,[Vendor] = ftlc.vendor
    ,[BusinessVertical] = ftlc.business_vertical
    ,[NumberOfLeads] = 1
    ,[dvce_type] = ftlc.dvce_type

    FROM [dbo].[Abc] d WITH (NOLOCK)

    LEFT JOIN [dt].[cde] cd WITH (NOLOCK) ON d.FullDate = 
    CAST(cd.CallDateTime AS DATE)

    LEFT JOIN [dt].[efg] c WITH (NOLOCK) ON cd.DialogtechCallId = 
    c.DialogTechCallid

    INNER JOIN [dt].[hij] m WITH (NOLOCK) ON cd.CallerId = 
    m.DialogTechPhoneNumber

    INNER JOIN [dt].[klm] bt WITH (NOLOCK) ON m.LeadSourceInfoId = 
    bt.LeadSourceId AND cd.[CallDateTime] BETWEEN bt.[StartDateTime]
    AND ISNULL(bt.[EndDateTime], GETDATE())

    INNER JOIN [dbo].[jkl] ftlc WITH (NOLOCK) ON bt.ParentLeadSource = 
    ftlc.fruit

    INNER JOIN dbo.xyz cpl WITH (NOLOCK) ON ftlc.lead_company =        
    cpl.lead_company AND cd.[CallDateTime] >= cpl.[start_date]
    AND cd.[CallDateTime] <= ISNULL(cpl.[end_date], GETDATE())

    WHERE CAST(cd.[CallDateTime] AS DATE) >= '2018-08-01'
    AND CASE WHEN ISNUMERIC(cd.[TalkTimeMinutes]) = 1
            THEN CASE 
                    WHEN CAST(cd.[TalkTimeMinutes] AS DECIMAL(10, 2)) * 60 
    >= CAST(bt.Billabletime AS INT)
                        THEN 1
                    WHEN bt.Billabletime = 900
                        THEN 1
                    ELSE 0
                    END
        ELSE 0
        END = 1
   ) sub

 GROUP BY 
 CallDate
,MediaChannel
,SubCategory
,Vendor
,BusinessVertical
,SourceName
,ParentLeadSource
,IsBillable
,dvce_type
,CostPerLead;

----该查询正在视图中使用,因此需要解决子查询问题并减少运行时间。

【问题讨论】:

  • 我会从解释选择开始看。您可以在同一个会话下进行几个查询,创建一个临时表,执行 ibsert 选择并使用结果
  • 有关查询优化的问题应包括表结构(如适用)以及示例数据。但是,在查看您的查询后,一些事情立即跳出来。 dbo.Abc 中有什么内容?您只使用FullDate 列对dt.cde 进行左连接。对于来自dbo.Abc 的值,您没有WHERE 条件,因此我可以看到这可能会返回大量与dt.cde 中的任何内容都不匹配的FullDate 值,从而导致将大量NULL 数据连接在一起.
  • @GuyLouzon 我有一个运行良好但对我没有用的临时表查询,因为我无法在创建视图语句中使用的 CTE 中使用它。 CREATE 视图 [dbo].[vw_cost] 与 cte_xyz 一样(上述查询)。
  • 简化,简化,简化。从一个简单的查询开始,然后添加新表以查看性能问题出在哪里。然后修复它。
  • @PandoraBox 然后我会尝试使用连接而不是子查询,我会尝试自己编写,但是您的查询很复杂...

标签: sql sql-server tsql ssms-2014


【解决方案1】:

您的子查询中有一些数据未在外部查询中使用。您的某些连接还可能将 NULL 值引入 NULL 值,这会影响您的性能。

在不知道您的表结构或函数以及任何实际数据的情况下,我想出了以下查询的简化版本。它从子查询中删除未使用的列、后续无用的连接、简化的 CASE 语句,以及从主查询中删除 CostPerLead,因为您正在聚合它。

SELECT
    CallDate
    ,MediaChannel
    ,SubCategory
    ,Vendor
    ,BusinessVertical
    ,NumberOfLeads   = COUNT(*)
    ,Cost            = NULLIF(SUM(CostPerLead), 0)
    ,SourceName
    ,ParentLeadSource
    ,IsBillable
    ,dvce_type
FROM
(



    SELECT
        CallDate            = CAST(cd.CallDateTime AS DATE)
        ,MediaChannel       = ftlc.channel2
        ,SubCategory        = ftlc.sub
        ,Vendor             = ftlc.vendor
        ,BusinessVertical   = ftlc.business_vertical
        ,CostPerLead        = CAST(cpl.cost AS INT)
        ,SourceName         = bt.LeadCompany
        ,ParentLeadSource   = ftlc.fruit
        ,IsBillable         = CASE WHEN ISNUMERIC(cd.TalkTimeMinutes) = 1
                                        AND (
                                                CAST(cd.TalkTimeMinutes AS DECIMAL(10, 2)) * 60 >= CAST(bt.Billabletime AS INT)
                                                OR
                                                bt.Billabletime = 900
                                            )
                                    THEN 1
                                    ELSE 0
                                 END
        ,dvce_type          = ftlc.dvce_type    
    FROM dbo.Abc       d WITH (NOLOCK)
    INNER JOIN dt.cde cd WITH (NOLOCK) ON d.FullDate = CAST(cd.CallDateTime AS DATE)
    INNER JOIN dt.hij  m WITH (NOLOCK) ON cd.CallerId = m.DialogTechPhoneNumber
    INNER JOIN dt.klm  bt WITH (NOLOCK) ON m.LeadSourceInfoId = bt.LeadSourceId
                                            AND cd.CallDateTime BETWEEN bt.StartDateTime AND ISNULL(bt.EndDateTime, GETDATE())
    INNER JOIN dbo.jkl ftlc WITH (NOLOCK) ON bt.ParentLeadSource = ftlc.fruit
    INNER JOIN dbo.xyz cpl WITH (NOLOCK) ON ftlc.lead_company = cpl.lead_company
                                             AND cd.CallDateTime BETWEEN cpl.start_date AND ISNULL(cpl.end_date, GETDATE())
    WHERE
        d.FullDate >= '2018-08-01'
        AND (
                ISNUMERIC(cd.TalkTimeMinutes) = 1 
                AND (
                        CAST(cd.TalkTimeMinutes AS DECIMAL(10, 2)) * 60 >= CAST(bt.Billabletime AS INT)
                        OR
                        bt.Billabletime = 900
                    )
            )
) sub
GROUP BY
    CallDate
    ,MediaChannel
    ,SubCategory
    ,Vendor
    ,BusinessVertical
    ,SourceName
    ,ParentLeadSource
    ,IsBillable
    ,dvce_type;

【讨论】:

    猜你喜欢
    • 2015-09-02
    • 2021-05-16
    • 1970-01-01
    • 1970-01-01
    • 2016-12-17
    • 2021-07-11
    • 2010-12-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多