优化SQL Server 2012中的视图所需的帮助

时间:2015-02-27 18:59:20

标签: sql-server views query-optimization

我正在运行SQL Server 2012并构建了一个查询,以减去一个主要的结果。我已经通过以下几种方式做到了这一点:

SELECT 
    campaignContact_id,
    nlLogID,
    emailAddress
FROM 
    sm_rel_campaign_contact rcc  
WHERE
    rcc.campaignContact_id NOT IN (SELECT campaignContact_id 
                                   FROM SM_BOUNCES) 

    AND rcc.campaigncontact_id NOT IN (SELECT campaignContact_id 
                                       FROM SM_DEFERRALS ) 
    AND rcc.campaignContact_id NOT IN (SELECT campaignContact_id 
                                       FROM SM_FAILS)
    AND rcc.campaignContact_id NOT IN (SELECT campaignContact_id 
                                       FROM SM_SENDS )

另一个是:

ALTER VIEW SM_QUEUE
AS
(
   SELECT 
      campaignContact_id,
      nlLogID,
      emailAddress
   FROM 
      sm_rel_campaign_contact rcc 
   WHERE 
      NOT EXISTS (SELECT * FROM SM_BOUNCES smb 
                  WHERE rcc.campaignContact_id = smb.campaignContact_id) 
      AND NOT EXISTS (SELECT * FROM SM_DEFERRALS smd 
                      WHERE rcc.campaignContact_id = smd.campaignContact_id)
      AND NOT EXISTS (SELECT * FROM SM_FAILS smf 
                      WHERE rcc.campaignContact_id = smf.campaignContact_id)
      AND NOT EXISTS (SELECT * FROM SM_SENDS sms 
                      WHERE rcc.campaignContact_id = sms.campaignContact_ID)
)

问题是在我创建视图后(无论哪种方式)运行此人:

SELECT count(*) 
FROM SM_QUEUE 
WHERE nlLogID = 81505

它的运行速度非常慢!我知道你可以索引视图,但我想知道是否有人有更好的建议? LEFT OUTER JOIN可能是吗?

提前感谢任何反馈。

4 个答案:

答案 0 :(得分:2)

您将无法为此视图编制索引 - 子查询或外部联接使其无法索引。

可能你在基表上缺少一些有用的索引。

may perform better

的可能不同方法
WITH Excludes
     AS (SELECT campaignContact_id
         FROM   SM_BOUNCES
         UNION ALL
         SELECT campaignContact_id
         FROM   SM_DEFERRALS
         UNION ALL
         SELECT campaignContact_id
         FROM   SM_FAILS
         UNION ALL
         SELECT campaignContact_id
         FROM   SM_SENDS)
SELECT campaignContact_id,
       nlLogID,
       emailAddress
FROM   sm_rel_campaign_contact rcc
WHERE  NOT EXISTS (SELECT *
                   FROM   Excludes e
                   WHERE  e.campaignContact_id = rcc.campaignContact_id) 

如果这样做无法帮助您编辑问题并包含CREATE TABLE语句,包括所涉及表格的索引和详细信息。

答案 1 :(得分:0)

'not in'通常不能被优化(最终使用全表扫描),但查询分析器可以优化不存在。看看你是否可以在第一个查询中将not in更改为not exists。

答案 2 :(得分:0)

真的不能尝试,因为sql小提琴已关闭,我没有sql server直到星期一(也许你需要更多的括号):

WITH cte AS (
  SELECT campaignContact_id FROM   sm_rel_campaign_contact rcc
  except
  SELECT campaignContact_id FROM   SM_BOUNCES
  except
  SELECT campaignContact_id FROM   SM_DEFERRALS
  except
  SELECT campaignContact_id FROM   SM_FAILS
  except
  SELECT campaignContact_id FROM   SM_SENDS)
SELECT *
from cte 
join sm_rel_campaign_contact rcc on rcc.campaignContact_id = cte.campaignContact_id 

答案 3 :(得分:0)

我希望第二个版本(WHERE NOT EXISTS())比WHERE NOT IN ()构造的版本运行得快一点。但是,这要求您在每个引用的表(campaignContact_idSM_BOUNCESSM_DEFERRALSSM_FAILS)中的SM_SENDS字段上都有索引。另外,既然你说这些是大表,那么你在nlLogID字段上开始有索引吗?很可能您的查询花费了更多时间来扫描sm_rel_campaign_contact表,而不是确定它是否在其他表中有相关​​数据;特别是因为你说问题中的两个版本都运行相同的'。 提示:尝试使用“显示执行计划”'运行查询。并解释那里发生了什么,或者只是截取屏幕截图并将其附加到上面的问题中,看看我们是否可以从中获得任何见解。