SQL Server 没有使用我的索引。如何使用我的索引?

Geo*_*e B 0 sql t-sql sql-server indexing

我的客户正在使用表格来创建每月的财务报告。我对其进行了优化,因为大约有 40 个聚合列,并且它运行了大约 40 分钟才能看到输出。我创建了一个将聚合值存储到表中的流程,现在,在选择列时,聚合已经计算完毕,并且运行时间为 3-4 分钟。现在我正在尝试创建一个索引,但由于数据量很大(我猜)SQL Server 没有使用它。查询非常简单

Select * 
From Table
Where year(data_doc) = 2023
and month(data_doc) = 10
Run Code Online (Sandbox Code Playgroud)

我仅为“data_doc”列创建了非聚集索引,但 SQL Server 仍然扫描整个表。我更改了索引并包含了构成主键的列,如下所示:

CREATE INDEX ix_Data_Doc ON Tabel(data_doc,OperationDetail_Id, OperationTraceOut_Id,OperationTraceIn_Id).
Run Code Online (Sandbox Code Playgroud)

重要的是,客户端正在使用视图,并且“select * from view”返回大约 5700 万行,总共有 57 列。每年和每月使用过滤器,它会返回大约 2/3 百万行。列“data_doc”数据类型为“datetime”。

如何创建索引来优化流程?

use*_*983 5

您的WHERE索引不是 SARGable(它不包含可搜索参数),因此该索引对于该查询“无用”,因为它无法使用。您需要使用日期范围,而不是WHERE.

SELECT <Explicit List of Columns you need>
FROM dbo.YourTable
WHERE Data_doc >= '20231001'
  AND Data_doc < '20231101';
Run Code Online (Sandbox Code Playgroud)

不过,您SELECTSELECT *怀疑该表中是否只有这 3 列。因此,即使查询是 SARGable,如果数据引擎估计执行(许多)键查找的成本比扫描更昂贵,它也可能会导致扫描。如果是这种情况,您可能需要将索引更改为INCLUDE表中的其他列,或者最好只返回您需要的表中的列(正如我在代码中建议的那样)并确保至少那些(其他)列都在INCLUDE.