4

これはしばらくの間私を悩ませてきました、そして私はSQLServerの専門家の1人がそれにいくらかの光を当てることができることを望んでいます。

質問は:

UDT(CLRタイプ)を含むSQL Server列にインデックスを付ける場合、SQL Serverは、特定のクエリに対して実行するインデックス操作をどのように決定しますか?

具体的にはhierarchyid(AKA SqlHierarchyID)タイプを考えています。マイクロソフトが推奨する方法、および私が使用する方法は次のとおりです。

  • 列自体にインデックスを作成しますhierarchyid(これを呼び出しましょうID)。これにより、深さ優先探索が可能になり、を記述したときにWHERE ID.IsDescendantOf(@ParentID) = 1インデックスシークを実行できるようになります。

  • 永続化された計算Level列を作成し、にインデックスを作成します(Level, ID)。これにより、幅優先探索が可能になり、を記述したときにWHERE ID.GetAncestor(1) = @ParentID、この式に対して(2番目のインデックスで)インデックスシークを実行できるようになります。

しかし、私が理解していないのは、これがどのように可能であるかということです。 これは通常のクエリプランのルールに違反しているようです。呼び出しは引数GetAncestorIsDescendantOfできないように見えるため、完全なインデックススキャンが実行されるはずですが、そうではありません明らかに不満を言っているわけではありませんが、この機能を自分のUDTで複製できるかどうかを理解しようとしています。

hierarchyidSQL Serverが特別に認識し、クエリ要素とインデックスの特定の組み合わせが見つかった場合に実行プランを自動的に変更する、単なる「魔法の」タイプですか?または、CLR型は、SQL Serverエンジンによって理解されるSqlHierarchyID特別な属性/メソッド(永続化された計算列の動作と同様)を単純に定義しますか?IsDeterministic

これに関する情報が見つからないようです。私が見つけたのは、IsByteOrderedインスタンスごとに1つの一意の表現を保証することで、プロパティがインデックスやチェック制約などを可能にすることを示す段落だけです。これはやや興味深いものですが、SQLServerが特定のインスタンスメソッドを使用してシークを実行する方法については説明していません。

では、もう一度質問します。インデックス操作は、のようなタイプに対してどのように機能します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 XMLNodeLabelsで説明されているメカニズムに似ています。したがって、IsDescendantとGetAncestorを使用するクエリを変換するQOルールは特別ですが、実際の基になるインデックスは、バイナリ階層IDデータの通常のリレーショナルインデックスであり、範囲シークを実行するために元のクエリを作成する場合は、同じ動作を実現できます。単純なメソッドを呼び出す代わりに。

于 2010-02-24T03:21:55.907 に答える