4

我有两张桌子

Account:
    AccountUID bigint (Primary Key)
    AccountID bigint
    Version smallint
    CustomerName varchar(50)

注意:AccountID 和 CurrentVersion 也是唯一键的一部分

AccountStatus:
    AccountID bigint (Primary Key)
    CurrentVersion smallint
    Filter1 varchar(10)
    Filter2 varchar(10))

为简单起见,我目前每行有 100 行,因为每行AccountID只有一个版本。我在Filter1Filter2表中有值,因此当我执行以下操作时,我会返回 10 条记录:

SELECT *
FROM AccountStatus acs
WHERE acs.Filter1=SomeValue1 and acs.Filter2=SomeValue2

由于我有一个包含Filter1and的索引,Filter2因此实际的执行计划显示了一个 Index Seek,其中只有 Actual Rows 值中的 10 个选定行。

Account当我按如下方式加入表时,我得到相同的 10 条记录:

SELECT acs.*
FROM AccountStatus acs
    INNER JOIN Account a ON acs.AccountID=a.AccountID
                            AND acs.CurrentVersion=a.Version
WHERE acs.Filter1=SomeValue1 and acs.Filter2=SomeValue2

但是,当我查看 Actual Execution Plan 时,我仍然可以看到AccountStatus桌面上的 Index Seek 和以前一样,有 10 个 Actual Rows。但是,在此之上,我看到索引扫描涉及表的AccountID 和。此外,此“动作”在实际行中显示 100。VersionAccount

以下是所涉及索引的详细信息:

CREATE NONCLUSTERED INDEX [IX_Find] ON [dbo].[AccountStatus] 
(
    [Filter1] ASC,
    [Filter2] ASC
)
INCLUDE ( [AccountID],
[CurrentVersion]
) 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]

CREATE UNIQUE NONCLUSTERED INDEX [IX_Account_Status] ON [dbo].[Account] 
(
    [AccountID] ASC,
    [Version] ASC
)
INCLUDE ( [AccountUID]) 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]

虽然这对 100 行的性能影响不大,但当我达到一百万或几百万行时,我更担心。这将变得非常低效。

有没有办法让这种类型的查询不扫描Account表上索引中的所有行?

任何帮助将不胜感激。

4

2 回答 2

1

执行计划基于表及其索引列的统计信息。只有 100 行,它的执行计划与它有 10m 行时不同。如果您担心它不使用索引,则需要增加数据量并更新统计信息,然后再查看执行计划。该引擎非常聪明,并且经常会选择执行计划的最快版本。

我假设过滤器 1 匹配相当数量的行,无论如何,引擎不需要花费太多时间来对这几行的搜索执行扫描,因此引擎只使用扫描。

于 2014-04-30T21:19:42.377 回答
0

我确定是否需要索引的方法是两种方法之一。第一个是使用 Display Estimated Execution Plan 执行查询。然后,如果执行计划显示缺少索引(绿色),请右键单击绿色的缺少索引消息并选择 Missing Index Details... 这将打开一个新窗口,其中包含插入可以帮助此查询的缺少索引的代码。只需取消注释代码的下部并替换为新索引的名称并执行代码。

对于可能有助于此代码的任何缺失索引,您可能需要重复此过程几次。

第二种方法更像是一种长期的数据库性能方法。

PINAL DAVE 在他的博客http://blog.sqlauthority.com/上发布了一系列脚本,帮助识别丢失的索引以及未使用和重复的索引。我定期运行这些以确定哪些索引会有所帮助,哪些实际上会损害性能。

添加缺少的索引并删除任何未使用或重复的索引。

于 2013-08-29T18:55:38.547 回答