【问题标题】:SQL Server Query Optimisation - What is the optimal index here?SQL Server 查询优化 - 这里的最佳索引是什么?
【发布时间】:2013-11-27 11:33:18
【问题描述】:

我有一个需要容纳超过 400 万行的电子邮件调度表。一个特定的报告也需要参考这个表格来产生一些统计数据,而且它需要的时间比我想运行的要长(目前大约 30 秒)。

我检查了估计的执行计划,这表明 94% 的成本是由单个谓词产生的(如果我解释正确的话)。

请注意,以下示例显示了小 sn-ps 以保持简短。针对其他查询的其他索引已经到位。

谓词:

[EmsDb].[dbo].[MailDispatchPending].[MailCampaignId]=[@MailCampaignId] OR [@MailCampaignId] IS NULL

我相信这指向以下 SQL:

WHERE @MailCampaignId IS NULL OR MailCampaignId = @MailCampaignId -- Restrict to mail campaign where parameter passed

我试图通过测试以下索引来提高性能。既不影响执行计划输出,也不提高查询速度。

/****** Object:  Index [IX_MailCampaignId]    Script Date: 11/27/2013 11:21:00 ******/
CREATE NONCLUSTERED INDEX [IX_MailCampaignId] ON [dbo].[MailDispatchPending] 
(
    [MailCampaignId] ASC

)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO

/****** Object:  Index [IX_MailCampaignId]    Script Date: 11/27/2013 11:21:00 ******/
CREATE NONCLUSTERED INDEX [IX_MailCampaignId] ON [dbo].[MailDispatchPending] 
(
    [Id] ASC,
    [MailCampaignId] ASC

)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO

谁能建议一种更好的索引类型或不同的策略来帮助我提高性能?

【问题讨论】:

    标签: sql sql-server indexing


    【解决方案1】:

    不要使用这种方法:

    WHERE @MailCampaignId IS NULL OR MailCampaignId = @MailCampaignId
    

    改为使用:

    IF @MailCampaignId IS NULL
        BEGIN
            SELECT  ..
            FROM    ...
        END
    ELSE
        BEGIN
            SELECT  ..
            FROM    ...
            WHERE   MailCampaignId = @MailCampaignId
        END 
    

    可能感觉工作量更大,但 SQL-Server 使用缓存的执行计划,除非您强制重新编译,否则无论参数是否为空,它都将使用相同的执行计划。如果您使用上述方法,您可以保证使用正确的计划,具体取决于参数是否为空

    【讨论】:

    • 不管参数值如何,这是关于使用相同执行计划的方便信息
    【解决方案2】:

    IS NULL OR 部分会影响您的性能,因为如果输入为 NULL,您将要求扫描的每一行。

    如果可能,我会删除该部分,看看是否没有帮助,如果不可能,那么我会重新考虑何时需要所有这些,并考虑另一种方法,例如多个查询而不是一个甚至是存储更改。

    【讨论】:

      【解决方案3】:

      这可能是@GarethD 提出的替代解决方案吗?

      WHERE MailCampaignId = COALESCE(@MailCampaignId,MailCampaignId)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-07-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-25
        • 2012-08-05
        • 1970-01-01
        相关资源
        最近更新 更多