我正在使用SQL Server 2008,它拒绝对覆盖计算列的索引执行搜索。
我的表格如下:
CREATE TABLE Person
{
Id uniqueidentifier NOT NULL,
InsertDate datetime NOT NULL,
PhoneNumber NULL,
PhoneNumberComparable AS (MakePhoneNumberComparable(PhoneNumber)) PERSISTED,
... etc...
}
ID列上有一个聚簇主键索引,还有InsertDate列上的索引。
PhoneNumberComparable计算列上有一个索引,如下所示:
CREATE NONCLUSTERED INDEX IX_Person_PhoneNumberComparable ON Person
(
PhoneNumberComparable ASC
)
索引都有最新的统计数据。
我的查询如下:
SELECT TOP 20 * FROM Person
WHERE PhoneNumberComparable = @PhoneNumber
ORDER BY InsertDate DESC
默认情况下,SQL Server决定使用InsertDate上的索引而不是PhoneNumberComparable上的索引,导致性能非常差。
如果我尝试强制使用电话号码索引,通过向查询添加WITH(INDEX = IX_Person_PhoneNumberComparable),SQL会尝试执行扫描,而不是搜索。
如果我尝试使用FORCESEEK查询提示,那么SQL Server会给我以下错误:
由于提示,查询处理器无法生成查询计划 在此查询中定义。重新提交查询而不指定任何提示 并且不使用SET FORCEPLAN。
所以基本上,由于某种原因,SQL Server拒绝寻求我的索引!为什么呢?
修改
根据评论中的建议,我简化了查询,但问题仍然存在(执行主键扫描而不是搜索电话号码索引):
SELECT TOP 20 PhoneNumberComparable FROM Person
WHERE PhoneNumberComparable = @PhoneNumber
答案 0 :(得分:5)
我相信我已经弄明白了。
问题是由于MakePhoneNumberComparable函数使用了另一个模式下的另一个函数。要解决这个问题,我必须克隆另一个函数的第二个副本,但是在与表相同的模式下移动它。
This article(感谢评论者Kahn)说,如果“计算列中的所有函数引用与表具有相同的所有者”,则只能定义索引。
那么,这个所有权要求不仅非常令人讨厌,而且至少可以说微软的文档非常令人困惑: