我有一个脚本,必须查看超过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
如何使用索引加快速度?
答案 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
条件)必须编入索引。
同样,作为拇指规则,我遵循以下标准:
date
字段编制索引char
或varchar
字段上进行频繁搜索,我也会将其编入索引请注意,很容易陷入索引所有内容的诱惑之中。不要这样做。小心并设计具有最佳成本 - 收益关系的索引。
我是MySQL用户,我不知道如何在SQL服务器中执行此操作,但必须有一种方法来显示查询的执行计划(在MySQL中它是explain select...
)。尝试显示执行计划,然后根据您的索引确定哪些字段。