这一直困扰着我一段时间,我希望 SQL Server 专家之一可以对此有所了解。
问题是:
当您索引包含 UDT(CLR 类型)的 SQL Server 列时,SQL Server 如何确定对给定查询执行的索引操作?
具体来说,我正在考虑hierarchyid
(AKA SqlHierarchyID
) 类型。Microsoft 建议您使用它的方式 - 以及我使用它的方式 - 是:
在列本身上创建索引
hierarchyid
(我们称之为ID
)。这启用了深度优先搜索,因此当您编写 时WHERE ID.IsDescendantOf(@ParentID) = 1
,它可以执行索引查找。创建一个持久计算
Level
列并在(Level, ID)
. 这启用了广度优先搜索,因此当您编写 时WHERE ID.GetAncestor(1) = @ParentID
,它可以为此表达式执行索引查找(在第二个索引上)。
但我不明白这怎么可能? 它似乎违反了正常的查询计划规则 - 调用GetAncestor
并且IsDescendantOf
似乎不是 sargable,所以这应该会导致完整的索引扫描,但事实并非如此。显然,我并不是在抱怨,而是我试图了解是否可以在我自己的 UDT 上复制此功能。
仅仅是hierarchyid
SQL Server 有特殊意识的一种“神奇”类型,如果找到查询元素和索引的某种组合,它会自动更改执行计划?还是CLR 类型只是定义了 SQL Server 引擎可以理解的SqlHierarchyID
特殊属性/方法(类似于持久计算列的工作方式)?IsDeterministic
我似乎找不到任何有关此的信息。我所能找到的只是一段说明该IsByteOrdered
属性通过保证每个实例的唯一表示来使索引和检查约束之类的事情成为可能;虽然这有点有趣,但它并没有解释 SQL Server 如何能够使用某些实例方法执行搜索。
那么问题又来了 - 索引操作如何适用于类似的类型hierarchyid
,是否有可能在新的 UDT 中获得相同的行为?