4

这一直困扰着我一段时间,我希望 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 上复制此功能。

仅仅是hierarchyidSQL Server 有特殊意识的一种“神奇”类型,如果找到查询元素和索引的某种组合,它会自动更改执行计划?还是CLR 类型只是定义了 SQL Server 引擎可以理解的SqlHierarchyID特殊属性/方法(类似于持久计算列的工作方式)?IsDeterministic

我似乎找不到任何有关此的信息。我所能找到的只是一段说明该IsByteOrdered属性通过保证每个实例的唯一表示来使索引和检查约束之类的事情成为可能;虽然这有点有趣,但它并没有解释 SQL Server 如何能够使用某些实例方法执行搜索。

那么问题又来了 - 索引操作如何适用于类似的类型hierarchyid,是否有可能在新的 UDT 中获得相同的行为?

4

2 回答 2

4

查询优化器团队正在尝试处理不改变事物顺序的场景。例如,cast(someDateTime as date)仍然是 sargable。我希望随着时间的推移,他们会修复一堆旧的,例如带有常量的 dateadd/datediff。

所以... 处理 Ancestor 实际上就像使用带有字符串开头的 LIKE 运算符一样。它不会改变顺序,你仍然可以逃脱惩罚。

于 2010-01-22T03:01:54.323 回答
2

你是对的 - HierarchyId 和 Geometry/Geography 都是查询优化器能够识别和重写计划以产生优化查询的“神奇”类型 - 它不像识别可搜索运算符那么简单。无法模拟其他 UDT 的等效行为。

对于 HierarchyId,类型的二进制序列化是特殊的,以便以二进制有序的方式表示层次结构。它类似于 SQL Xml 类型使用的机制,并在研究论文ORDPATHs: Insert-Friendly XML Node Labels中进行了描述。因此,虽然使用 IsDescendant 和 GetAncestor 转换查询的 QO 规则很特殊,但实际的底层索引是二进制 hierarchyid 数据上的常规关系索引,如果您愿意编写原始查询来进行范围搜索,则可以实现相同的行为而不是调用简单的方法。

于 2010-02-24T03:21:55.907 回答