SQL Server查询优化 - 这里的最佳索引是什么?
问题描述:
我有一个需要超过400万行持有的电子邮件调度表。一个特别的报告还需要参考该表产生一些统计数据,而且它花费的时间比我想运行(目前大约30秒)。SQL Server查询优化 - 这里的最佳索引是什么?
我已经检查了估计的执行计划,其示出了成本的94%是由一个单一谓词发生(如果我正确地解释这一点)。
注意以下示例所示小片段,以保持简洁。其他索引适用于其他查询。
谓:
[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
任何人都可以提出更好的索引类型或不同的策略来帮助我提高性能吗?
答
不要使用这种方法:
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使用缓存的执行计划,除非你强行重新编译它将使用相同的执行计划,无论参数是否为空。如果你使用上面的方法,你保证使用正确的计划取决于参数是否为空
答
的IS NULL OR
部分是做什么用你的表现搞乱,因为如果输入为NULL你问的每一行是扫描。
如果可能的话我会删除部分,看看是否有没有帮助,如果没有可能,那么我会重新考虑的时候我需要所有这些,例如考虑多个查询的另一种方法,而不是一个甚至存储的变化。
答
可以这是一个由@GarethD提出的替代解决方案吗?
WHERE MailCampaignId = COALESCE(@MailCampaignId,MailCampaignId)
无论参数值如何,这都是关于使用相同执行计划的方便信息 – gb2d