索引扫描而不是搜索

时间:2014-12-12 14:25:15

标签: sql sql-server sql-execution-plan

我在桌面上添加了一个新的计算列:

ALTER TABLE MyTable
ADD DATAORA_STOCK AS (Data_stock + Ora_Stock)

Data_Stock类型为char(8)Ora_Stock类型为char(6)

在此DATAORA_STOCK列中创建新的非聚集索引之后:

CREATE NONCLUSTERED INDEX [IX_MyTable_DATAORA_STOCK] ON MyTable
(
    [DATAORA_STOCK] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO

当我执行这两个查询时:

SELECT * FROM MyTable
WHERE DATAORA_STOCK = @Data1

SELECT * FROM MyTable
WHERE DATAORA_STOCK >= @Data1

我有两个不同的执行计划。首先查询IX_MyTable_DATAORA_STOCK并进行密钥查找。

为什么第二次在聚簇索引上执行扫描索引?

使用OPTION(RECOMPILE)它运作良好,实际(未估计)执行计划是正确的。 不幸的是我无法修改查询文本,因为它是从应用程序中调用的... 我已经更新了我桌上的统计数据,但没有任何变化 确切的查询文本是:

SELECT * 
FROM MyView
WHERE DatAgg+OraAgg >= @Data1 AND DatAgg+OraAgg <= @Data2 

原始表格中DatAgg+OraAggDATAORA_STOCK(视图只是MyTable的投影),而DATAORA_STOCK是计算列。

1 个答案:

答案 0 :(得分:2)

因为索引不覆盖,并且它估计

返回的行数
  WHERE DATAORA_STOCK >= @Data1

将导致如此多的查找以检索丢失的列值,以便扫描整个内容更便宜。

如果估算错误,您可以尝试使用OPTION (RECOMPILE)来嗅探@Data1的值(如果估算仍然错误,请更新该列的统计信息)