索引如何在SQL用户定义类型(UDT)上工作?

时间:2010-01-11 15:39:59

标签: sql-server performance sql-server-2008 clr sqlclr

这一直困扰着我一段时间,我希望其中一位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时,它可以为此表达式执行索引搜索(在第二个索引上)。

但我不明白的是这怎么可能?这似乎违反了正常的查询计划规则 - 对GetAncestorIsDescendantOf的调用没有似乎是sargable,所以 应该导致完整的索引扫描,但事实并非如此。显然,并非我抱怨,但我想了解是否可以在我自己的UDT上复制此功能。

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

我似乎无法找到有关此内容的任何信息。我能够找到的是一个段落,声明IsByteOrdered属性通过保证每个实例有一个唯一的表示,使索引和检查约束成为可能。虽然这有点有趣,但它没有解释SQL Server如何使用某些实例方法执行 seek

再次提出问题 - 索引操作如何适用于hierarchyid之类的类型,是否可以在新的UDT中获得相同的行为?

2 个答案:

答案 0 :(得分:4)

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

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

答案 1 :(得分:2)

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

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