SQL语句 - 如何通过索引提高速度

时间:2013-03-25 17:31:43

标签: sql sql-server sql-server-2008

我有一个脚本,必须查看超过250万条记录,以查找是否有未读电子邮件的成员。我想知道如何提高速度。目前,运行脚本最多需要8秒钟:

SELECT TOP(1) MemberMailID
FROM MemberMail
WHERE ToReadFlag = 0
AND ToMemberID = 102
AND ToDeletedFlag = 0
AND FromDeletedFlag = 0
AND OnHold = 0
AND ToArchivedFlag = 0

如何使用索引加快速度?

4 个答案:

答案 0 :(得分:4)

此索引可能会有所帮助,但请记住,没有免费午餐(必须维护索引,因此这会影响您的插入/更新/删除工作量):

CREATE NONCLUSTERED INDEX unread_emails
  ON dbo.MemberMail(ToMemberID)
  INCLUDE (MemberMailID)
  WHERE ToReadFlag = 0
  AND ToDeletedFlag = 0
  AND FromDeletedFlag = 0
  AND OnHold = 0
  AND ToArchivedFlag = 0;

现在您的查询可以说:

SELECT TOP (1) MemberMailID
  FROM dbo.MemberMail -- dbo prefix
    WITH (INDEX (unread_emails)) -- in case you need to force, though you should not
WHERE ToMemberID = 102
AND ToReadFlag = 0
AND ToDeletedFlag = 0
AND FromDeletedFlag = 0
AND OnHold = 0
AND ToArchivedFlag = 0
ORDER BY ToMemberID; -- ORDER BY is important!

如果根据查询更改某些标记的值,您可以尝试将这些列添加到索引的键而不是过滤器,例如假设您有时检查OnHold = 0,有时检查OnHold = 1

CREATE NONCLUSTERED INDEX unread_emails
  ON dbo.MemberMail(ToMemberID, OnHold)
  INCLUDE (MemberMailID)
  WHERE ToReadFlag = 0
  AND ToDeletedFlag = 0
  AND FromDeletedFlag = 0
  AND ToArchivedFlag = 0;

您可能还想尝试在密钥中使用MemberMailID而不是INCLUDE。 e.g:

CREATE NONCLUSTERED INDEX unread_emails
  ON dbo.MemberMail(ToMemberID, MemberMailID)
  WHERE ToReadFlag = 0
  AND ToDeletedFlag = 0
  AND FromDeletedFlag = 0
  AND OnHold = 0
  AND ToArchivedFlag = 0;

这些差异可能对您的数据和使用模式无关紧要,但您可以比我们猜测的更容易测试差异。

答案 1 :(得分:3)

看起来像filtered index的好候选人。

  

过滤索引是优化的非聚簇索引,尤其适合   覆盖从明确定义的数据子集中选择的查询。它   使用过滤谓词来索引表中的一部分行。一个   精心设计的过滤索引可以提高查询性能,减少   索引维护成本,与降低索引存储成本相比   全表索引。

这些方面的东西:

CREATE NONCLUSTERED INDEX IX_MemberMail_ToMemberId_Unread
ON dbo.MemberMail (ToMemberId ASC)
WHERE ToReadFlag = 0
AND ToDeletedFlag = 0
AND FromDeletedFlag = 0
AND OnHold = 0
AND ToArchivedFlag = 0;

答案 2 :(得分:2)

在SSMS中按(CTRL + M)获取实际查询计划。或者将您的查询粘贴到SSMS中,右键单击它,选择分析数据库引擎优化顾问中的查询,您将看到需要添加的索引。基本上,您需要复合+包含索引。

答案 3 :(得分:0)

作为一个拇指规则,每个字段,您执行频繁过滤(where条件)必须编入索引。

同样,作为拇指规则,我遵循以下标准:

  1. 必须为每个关键字段(主要或外国)编制索引
  2. 必须对我必须执行频繁查找的每个date字段编制索引
  3. 虽然我避免使用它,但如果我需要在charvarchar字段上进行频繁搜索,我也会将其编入索引
  4. 请注意,很容易陷入索引所有内容的诱惑之中。不要这样做。小心并设计具有最佳成本 - 收益关系的索引。

    我是MySQL用户,我不知道如何在SQL服务器中执行此操作,但必须有一种方法来显示查询的执行计划(在MySQL中它是explain select...)。尝试显示执行计划,然后根据您的索引确定哪些字段。