2016-02-26 11 views
3

我在SQL Server 2008 R2以下查询:SQL查询,包括不喜欢或者子查询当前行引用时速度极慢

SELECT 
    DateName(month, DateAdd(month, [sfq].[fore_quart_month], -1)) AS [Month], 
    [sfq].[fore_quart_so_rev] AS [Sales Orders Revenue], 
    [sfq].[fore_quart_so_mar] AS [Sales Orders Margin], 
    [sfq].[fore_quart_mac_rev] AS [MAC Revenue], 
    [sfq].[fore_quart_mac_mar] AS [MAC Margin], 
    [sfq].[fore_quart_total_rev] AS [TOTAL Revenue], 
    [sfq].[fore_quart_total_mar] AS [TOTAL Margin], 
    (SELECT SUM([FORE].[Revenue]) 
    FROM [SO_Opportunity][SO] 
    LEFT JOIN [SO_Type] ON [SO].[SO_Type_RecID] = [SO_Type].[SO_Type_RecID] 
    LEFT JOIN [SO_Opportunity_Audit][soa] ON [so].[Opportunity_RecID] = [soa].[Opportunity_RecId] 
    LEFT JOIN [SO_Opportunity_Audit_Value][soav] ON [soa].[SO_Opportunity_Audit_RecId] = [soav].[SO_Opportunity_audit_recid] 
    LEFT JOIN [SO_Forecast_dtl] [FORE] ON [SO].[Opportunity_RecID] = [FORE].[Opportunity_RecID] 
    WHERE ([SO_Type].[Description] NOT LIKE '%MAC%' AND [SO_Type].[Description] NOT LIKE '%Maint%') 
     AND YEAR([soa].[last_Updated_utc]) = @p_year AND MONTH([soa].[last_updated_utc]) = [sfq].[fore_quart_month] 
     AND [soav].[audit_value] LIKE '%Closed - Won%' AND [soav].[audit_token] = 'new_value' 
     AND [so].[SO_Opp_Status_RecID] = 7) AS [Rev] 
FROM 
    [authmanager2].[dbo].[sales_forecast_quarterly][sfq] 
WHERE 
    [sfq].[fore_quart_year] = @p_year AND [sfq].[fore_quart_loc] = 'w' 
ORDER BY 
    [sfq].[fore_quart_month] 

的问题是,包括NOT LIKE过滤器和[sfq].[fore_quart_month]参考时在子查询中,它的运行速度非常慢(分钟),但是如果我删除NOT LIKE筛选器或者硬设置值而不是使用[sfq].[fore_quart_month](这显然意味着每个计算都会使用错误的月份,除了硬编码的那个月份) ,那么查询运行时间不到一秒钟。

有什么建议吗?

+1

桌子上有哪些索引?您的查询计划如何查看?这里有很多表达式,如果它存在的话可以被重写来利用索引。例如,避免在字段周围放置表达式,因为这会阻止索引利用率。例如,使用'[soa]。[last_updated_utc] BETWEEN @startdate AND @ enddate'。即使这不适合你的输入参数,试着看它是否会提高性能 –

+0

首先,你实际上已经在'so_type','soa'和'soav'的子查询中加入了'INNER'。不要纠结查询优化器。 '[sfq]。[fore_quart_loc]'是外部查询的唯一链接。如果你评论它,那么仅执行一次子查询就足够了 - 当然它会更快。检查你的执行计划。以'%'开头的'LIKE'对于谓词中的转换性能不好。 –

回答

0

使用两端通配符的LIKE查询非常慢。例如:%MAC%

如果您真的需要搜索,请考虑创建一个持续计算的布尔值字段并在其上进行搜索。喜欢的东西:

ALTER TABLE SO_Type 
ADD IsMac AS CASE WHEN [Description] LIKE '%MAC%' THEN 1 ELSE 0 END PERSISTED 
GO 

OR

作为替代方案,设置ISMac只要将数据插入

0

小提示:您可以按月份和团体加入子查询到主数据源中from条款。这将让(不是必须)服务器只执行一次子查询。请注意我上面的评论。

... 
FROM [authmanager2].[dbo].[sales_forecast_quarterly][sfq] 
INNER JOIN 
(
    SELECT SUM([FORE].[Revenue]) as [Revenue], MONTH([soa].[last_updated_utc]) as [Month] 
    FROM [SO_Opportunity][SO] 
    INNER JOIN [SO_Type] ON [SO].[SO_Type_RecID] = [SO_Type].[SO_Type_RecID] 
    ... 
    GROUP BY MONTH([soa].[last_updated_utc]) 
) rev on rev.[Month] = [sfq].[fore_quart_month]