这个问题已经困扰我一段时间了,我希望一位 SQL Server 专家能够对此做出一些解释。
问题是:
当您对包含 UDT(CLR 类型)的 SQL Server 列建立索引时,SQL Server 如何确定对给定查询执行什么索引操作?
具体来说,我想到的是 hierarchyid
(又名 SqlHierarchyID
)类型。 Microsoft 建议您使用它的方式 - 以及我使用它的方式 - 是:
在
hierarchyid
列本身上创建索引(我们称之为ID
)。这可以实现深度优先搜索,因此当您编写WHERE ID.IsDescendantOf(@ParentID) = 1
时,它可以执行索引查找。创建持久计算的
Level
列并在(Level, ID)
上创建索引。这可以实现广度优先搜索,因此当您编写WHERE ID.GetAncestor(1) = @ParentID
时,它可以为此表达式执行索引查找(在第二个索引上)。
但我不明白的是这怎么可能?它似乎违反了正常的查询计划规则 - 对GetAncestor
和IsDescendantOf<的调用
似乎不可控制,因此这应该导致完整索引扫描,但事实并非如此。显然,我并不是在提示,而是我试图了解是否可以在我自己的 UDT 上复制此功能。
hierarchyid 是否只是 SQL Server 具有特殊感知能力的“神奇”类型,如果它发现查询元素和索引的特定组合,它会自动更改执行计划?或者 SqlHierarchyID
CLR 类型是否只是定义 SQL Server 引擎可以理解的特殊属性/方法(类似于 IsDeterministic
用于持久计算列的方式)?
我似乎找不到任何有关此的信息。我所能找到的只是一段文字,指出 IsByteOrdered 属性通过保证每个实例有一个唯一的表示来使索引和检查约束之类的事情成为可能;虽然这有点有趣,但它并没有解释 SQL Server 如何使用某些实例方法执行seek。
那么问题又来了 - 索引操作如何适用于像 hierarchyid 这样的类型,以及是否有可能在新的 UDT 中获得相同的行为?
最佳答案
查询优化器团队正在尝试处理不改变事物顺序的场景。例如,cast(someDateTime as date)
仍然是可控制的。我希望随着时间的推移,他们会修复一些旧的,例如带有常量的 dateadd/datediff 。
所以...处理 Ancestor 实际上就像在字符串开头使用 LIKE 运算符一样。它不会改变顺序,而且你仍然可以逃脱惩罚。
关于sql-server - 索引如何在 SQL 用户定义类型 (UDT) 上工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2042826/