我有两张 table
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
只有一个版本。我在 Filter1
中有值和 Filter2
表,这样当我执行以下操作时,我会返回 10 条记录:SELECT *
FROM AccountStatus acs
WHERE acs.Filter1=SomeValue1 and acs.Filter2=SomeValue2
由于我有一个索引
Filter1
和 Filter2
在里面,实际的执行计划显示了一个索引搜索,在实际行值中只有 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
但是,当我查看实际执行计划时,我仍然看到
AccountStatus
上的Index Seek。表和以前一样,有 10 个实际行。但是,在上面我看到索引上的索引扫描涉及
AccountID
和 Version
的Account
table 。此外,此“操作”在实际行中显示 100。
以下是所涉及索引的详细信息:
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
上索引中的所有行? table ?任何帮助将不胜感激。
最佳答案
执行计划基于表及其索引列的统计信息。只有 100 行时,它将具有与 10m 行时不同的执行计划。如果您担心它不使用索引,则需要在再次查看执行计划之前增加数据量并更新统计信息。该引擎非常聪明,通常会选择执行计划的最快版本。
我假设过滤器 1 匹配相当数量的行,无论如何,引擎在这几行的搜索中执行扫描不会花费更长的时间,因此引擎只使用扫描。
关于sql-server - 为什么内部联接会产生索引扫描与索引查找,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18158574/