代码之家  ›  专栏  ›  技术社区  ›  Aaronaught

索引如何处理SQL用户定义类型(UDT)?

  •  4
  • Aaronaught  · 技术社区  · 15 年前

    这已经困扰了我一段时间了,我希望有一位SQL Server专家能对它有所了解。

    问题是:

    当索引包含UDT(clr类型)的SQL Server列时,SQL Server如何确定要为给定查询执行什么索引操作?

    具体来说,我想 hierarchyid (阿卡 SqlHierarchyID )类型。微软建议您使用它的方式——以及我使用它的方式——是:

    • 在上创建索引 层次结构 列本身(我们称之为 ID )这将启用深度优先搜索,以便在编写 WHERE ID.IsDescendantOf(@ParentID) = 1 ,它可以执行索引查找。

    • 创建持久化计算 Level 列并在上创建索引 (Level, ID) . 这将启用广度优先搜索,以便在编写 WHERE ID.GetAncestor(1) = @ParentID ,它可以为此表达式执行索引查找(在第二个索引上)。

    但我不明白的是 这怎么可能? 它似乎违反了正常的查询计划规则-调用 GetAncestor IsDescendantOf 看起来不适合穿,所以这个 应该 结果是一个完整的索引扫描,但没有。显然不是我在抱怨,但我试图理解是否有可能在我自己的UDT上复制这个功能。

    层次结构 只是SQL Server特别了解的“神奇”类型,如果发现查询元素和索引的某种组合,它会自动更改执行计划?或者做 Sql层次结构 clr类型只定义特殊的属性/方法(类似于 IsDeterministic 是否适用于SQL Server引擎可以理解的持久化计算列?

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

    所以问题又来了——索引操作如何适用于像这样的类型 层次结构 在一个新的UDT中是否有可能获得相同的行为?

    2 回复  |  直到 15 年前
        1
  •  4
  •   Rob Farley    15 年前

    查询优化器团队正在尝试处理不改变事情顺序的场景。例如, cast(someDateTime as date) 还是可以说的。我希望随着时间的推移,它们会修复一些旧的问题,比如带有常量的dateadd/datediff。

    所以…处理祖先实际上就像在字符串的开头使用like运算符。它不会改变你的顺序,而且你仍然可以摆脱这些东西。

        2
  •  2
  •   stevehem    15 年前

    您是正确的-HierarchyID和几何/地理都是查询优化器能够识别和重写计划以生成优化查询的“神奇”类型-这不像只识别可搜索的运算符那么简单。无法用其他UDT模拟等效行为。

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