【问题标题】:DB Engine Tuning Advisor suggestion improvementDB Engine Tuning Advisor 建议改进
【发布时间】:2015-06-12 09:37:12
【问题描述】:

我们有一个表格,其中包含所有准备发送且已发送的电子邮件。该表包含超过 100 万行。

以下是查找仍需发送的消息的查询。 5 次错误后,该消息不再尝试,需要手动修复。在发送消息之前,SentDate 仍为 null

SELECT TOP (15) 
    ID,
    FromEmailAddress,
    FromEmailDisplayName,
    ReplyToEmailAddress,
    ToEmailAddresses,
    CCEmailAddresses,
    BCCEmailAddresses,
    [Subject],
    Body,
    AttachmentUrl
FROM sysEmailMessage
WHERE ErrorCount < 5 
AND SentDate IS NULL
ORDER BY CreatedDate 

查询速度很慢,我认为是因为缺少索引。我已将查询提供给数据库引擎优化顾问。它建议了以下索引(以及一些我通常忽略的统计数据):

SET ANSI_PADDING ON

CREATE NONCLUSTERED INDEX [_dta_index_sysEmailMessage_7_1703677117__K14_K1_K12_5_6_7_8_9_10_11_15_17_18] ON [dbo].[sysEmailMessage]
(
    [SentDate] ASC,
    [ID] ASC,
    [ErrorCount] ASC
)
INCLUDE (   [FromEmailAddress],
    [ToEmailAddresses],
    [CCEmailAddresses],
    [BCCEmailAddresses],
    [Subject],
    [Body],
    [AttachmentUrl],
    [CreatedDate],
    [FromEmailDisplayName],
    [ReplyToEmailAddress]) WITH (SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF) ON [PRIMARY]

(附带说明:此索引的建议大小为 5,850,573 KB (?),接近 6 GB,对我来说根本没有任何意义。)

我的问题是这个建议的索引是否有意义?例如,为什么包含 ID 列,而查询中不需要它(据我所知)? 就我对索引的了解而言,它们旨在快速查找以找到相关行。如果我必须自己设计索引,我会想出类似的东西:

SET ANSI_PADDING ON

CREATE NONCLUSTERED INDEX [index_alternative_a] ON [dbo].[sysEmailMessage]
(
    [SentDate] ASC,
    [ErrorCount] ASC
)
WITH (SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF) ON [PRIMARY]

优化器真的很聪明,还是我的索引更高效并且可能更好?

【问题讨论】:

  • 它可能建议使用 ID 来更快地查找聚集索引。但是,我会使用您的索引,但将 CreatedDate 添加到索引列中,并且可能包括(您选择列表中的所有其他列)。
  • 该查询的最佳索引是CREATE INDEX ix on sysEmailMessage(CreatedDate) WHERE ErrorCount &lt; 5 AND SentDate IS NULL。它没有覆盖,但您只会得到 15 次查找,因为它只需要按顺序处理过滤后的索引并在 15 行后停止。

标签: sql-server query-optimization database-tuning-advisor


【解决方案1】:

选择索引有 2 个不同的方面,查找行所需的字段(=实际索引字段)和之后需要的字段(=包含的字段)。如果你总是做前 15 行,你可以完全忽略包含的字段,因为 15 次键查找会很快 - 将整个电子邮件添加到索引中会变得很大。

对于索引字段,了解有多大比例的数据符合您的条件非常重要。

假设您的几乎所有行的 ErrorCount

假设 SentDate 很少为 NULL,那么您应该将它作为索引的第一列。

索引中有 CreatedDate 取决于从具有 ErrorCount 和 SentDate 条件的表中找到的平均行数。如果它很多(数千个),那么将它放在那里可能会有所帮助,以便可以快速找到最新的。

但与往常一样,有几件事会影响性能,因此您应该测试不同的选项如何影响您的环境。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-11-09
    • 1970-01-01
    • 2023-03-20
    • 1970-01-01
    • 1970-01-01
    • 2010-10-26
    • 2023-03-27
    • 1970-01-01
    相关资源
    最近更新 更多