正确使用索引来优化查询

Viv*_*ekh 3 performance index sql-server azure-sql-database performance-tuning

我有一个包含数百万条记录的 SQL 数据库,当我查询数据时

select * from ActCosts where ScenarioID= 456
Run Code Online (Sandbox Code Playgroud)

这些表有 1,323,718 行,它给了我 50,000 多行,这令人惊讶地花费了 3 多分钟。所以我现在正在考虑如何改进这个性能。我发现一种方法是在“SomeID”列上创建索引。我已经创建了这个索引,但查询需要相同的时间

在此处输入图片说明

执行计划 在此处输入图片说明

索引脚本

CREATE NONCLUSTERED INDEX [IX_ActCost_ScenarioID] ON [dbo].[ActCost] 
(
    [ScenarioID] ASC
)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)
GO


ALTER TABLE [dbo].[ActCost] ADD  CONSTRAINT [PK_ActCost] PRIMARY KEY CLUSTERED 
(
    [ActCostID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON)
GO
Run Code Online (Sandbox Code Playgroud)

Mar*_*son 8

使用索引查询并不会更快,因为 SQL Server 已确定执行聚集索引扫描比使用IX_ActCost_ScenarioID您定义的并执行键查找来检索所需的额外数据更有效。

由于您只在 上定义了索引ScenarioID,没有INCLUDE列,因此您希望从查询返回的每个额外列都需要从聚集索引中检索。在 50,000+ 行上,这根本不会有效,因此索引被忽略。

首先,您需要问自己是否真的需要返回所有列。我以某种方式怀疑你这样做(例如 ID 列),但我可能是错的。 在任何情况下,您都应该始终定义列列表而不是使用*.

SELECT
 ActID, 
 ActCostTypeID,
 Description,
 Cost,
 <rest_of_columns...>
FROM dbo.ActCosts 
WHERE ScenarioID = 456;
Run Code Online (Sandbox Code Playgroud)

注意:
1.不要避免使用schema 前缀
2.避免使用SELECT *

然后,您需要包含在 中返回的额外列IX_ActCost_ScenarioID

CREATE NONCLUSTERED INDEX [IX_ActCost_ScenarioID] ON [dbo].[ActCost] ([ScenarioID] ASC)
INCLUDE ( <list_all_other_columns_returned> );
GO
Run Code Online (Sandbox Code Playgroud)