我有具有树结构的表(由hierarchyid
列定义),我想选择特定记录的所有后代。为此,我正在使用hiearchyid.IsDescendantOf()
方法。
我预计,由于我不进行简单的比较,但我正在执行操作(在本例中我调用该IsDescendantOf()
方法),那么我将得到一些带有索引扫描等的可怕执行计划。
然而,SQL Server 将其优化为漂亮的小索引查找。
我很困惑为什么以及如何。
CLR 类型上的调用方法通常会被优化吗?我假设 SQL Server 将 CLR 类型视为不透明的黑匣子,因此无法发挥其魔力。(因为它也无法在本机 SQL 函数上执行此操作。)
或者这仅适用于该特定方法?(由于这些hieararchyid
值是按深度优先排序的,因此我只需通过比较就可以获得类似的结果。)
演示:
CREATE TABLE dbo.HierarchyExample (
Id INT PRIMARY KEY,
Hieararchy HIERARCHYID NOT NULL
);
INSERT INTO dbo.HierarchyExample(Id, Hieararchy)
VALUES
(1, hierarchyid::Parse('/1/')),
(2, hierarchyid::Parse('/1/1/')),
(3, hierarchyid::Parse('/1/2/')),
(4, hierarchyid::Parse('/1/3/')),
(5, hierarchyid::Parse('/1/3/1/')),
(6, hierarchyid::Parse('/1/3/2/')),
(7, hierarchyid::Parse('/1/3/3/')),
(8, hierarchyid::Parse('/1/4/')),
(9, hierarchyid::Parse('/1/4/1/')),
(10, hierarchyid::Parse('/1/4/2/'));
CREATE INDEX IX_HierarchyExample_Hierarchy
ON dbo.HierarchyExample (Hieararchy);
SELECT descendant.*
FROM HierarchyExample ancestor
INNER JOIN HierarchyExample descendant
ON descendant.Hieararchy.IsDescendantOf(ancestor.Hieararchy) = 1
WHERE ancestor.Id = 1
DROP TABLE IF EXISTS dbo.HierarchyExample;
descendant.Hieararchy.IsDescendantOf(ancestor.Hieararchy) = 1
当然看起来它不应该是可控制的,但它似乎在这个特定案例的过程中很早就做了一些恶作剧。如果我尝试
由此产生的执行计划显示了对
范围表达式已存在于转换后的树中。
所以我得出的结论是,在解析过程中,它会转换为潜在的可查找范围谓词。
在论文《对灵活模式场景的关系支持》中提到了这种转换,尽管它没有详细介绍。
此后优化就会正常进行。之后使用的查询转换规则只是
SelIdxToRng
-SelToTrivialFilter
没有任何特定于 HierarchyId 的规则。下面是更复杂的连接示例的转换后的树,显示的内容大致相同