sql >> データベース >  >> RDS >> Sqlserver

SQL Server HierarchyID の深さ優先のパフォーマンスに関する質問

    深さ優先検索と幅優先検索のどちらを最適化しようとしているのかは完全には明らかではありません。質問は深さ優先を示唆していますが、最後のコメントは幅優先です。

    深さ優先に必要なすべてのインデックスがあります (hierarchyid にインデックスを付けるだけです) 桁)。幅優先の場合、作成するだけでは十分ではありません 計算された level 列にもインデックスを付ける必要があります:

    ALTER TABLE Message
    ADD [Level] AS MessageID.GetLevel()
    
    CREATE INDEX IX_Message_BreadthFirst
    ON Message (Level, MessageID)
    INCLUDE (...)
      

    (クラスター化されていないインデックスの場合、おそらく INCLUDE が必要になることに注意してください - そうしないと、SQL Server は代わりにクラスター化インデックス スキャンを実行することになります。)

    ここで、すべての先祖を見つけようとしている場合 ノードの、少し異なるタックを取りたいです。 hierarchyid の優れた点は、これらの検索を非常に高速に実行できることです。 - 各ノードには、そのすべての祖先が既に「含まれています」。

    これをできるだけ速くするために CLR 関数を使用しますが、再帰 CTE を使用して実行することもできます:

    CREATE FUNCTION dbo.GetAncestors
    (
        @h hierarchyid
    )
    RETURNS TABLE
    AS RETURN
    WITH Hierarchy_CTE AS
    (
        SELECT @h AS id
    
        UNION ALL
    
        SELECT h.id.GetAncestor(1)
        FROM Hierarchy_CTE h
        WHERE h.id <> hierarchyid::GetRoot()
    )
    SELECT id FROM Hierarchy_CTE
      

    ここで、すべての祖先と子孫を取得するには、次のように使用します:

    DECLARE @MessageID hierarchyID   /* passed in from application */
    
    SELECT m.MessageID, m.MessageComment 
    FROM Message as m
    WHERE m.MessageId.IsDescendantOf(@MessageID) = 1
    OR m.MessageId IN (SELECT id FROM dbo.GetAncestors(@MessageID.GetAncestor(1)))
    ORDER BY m.MessageID
      

    試してみてください - これでパフォーマンスの問題が解決するはずです。



    1. Eloquent:関係のどこに電話するか

    2. SQLServerの監視を担当するDBAに影響を与える上位3つのトレンド

    3. エポックタイムスタンプをSQLサーバーに変換する(人間が読める形式)

    4. ORA-01745 c#でパラメータ化されたクエリを実行中にエラーが発生しました