再帰的なCTEパフォーマンス


8

再帰的なCTEパフォーマンスのヘルプが必要です。CTE以下では、階層データを再帰的にプルしようとしているため、実行速度が非常に遅くなっています。テーブルは大きく、すべてのルートIDに最大3つの再帰的なアイテムIDがあります。約200000以上のルートIDが存在する可能性があります。アンカーのすべてのrootidは再帰的にitemidになるため、再帰的なCTEは巨大なデータセットでは遅いことを知っています。

スキーマ:

Create table RootItem (ItemId int primary key, RootIt int , insertdate datetime)

上記の表には100万行を超える行があります。

CTEクエリ:

; With rootcte as

( select itemid from RootItem where rootid is null

union all

  select r.itemid as RootId , i.itemid from RootItem i join rootcte r
    on i.rootid = r.itemid
)

テーブルスキーマを変更してheirarchyidを使用することはできません。whileループも試しましたが、それも遅いです。

このクエリを最適化できる他の方法はありますか?

 ; With rootcte as

( select itemid from RootItem where rootid is null

 union all

 select r.itemid as RootId , i.itemid from RootItem i join rootcte r
 on i.rootid = r.itemid
) 
  SELECT  
     Cust.CustomerID  
    , Cust.BusinessName  
    , sCust.RegionCustomerID  
    , ord.OrderID  
    , ord.OrderItemID  
    , prd.ProductCode  
    , rc.itemid
    , rc.rootid 
    , mf.FileID  
FROM  
    vw_Customer Cust  
    INNER JOIN SrcCustomer scust ON Cust.CustomerID = sCust.RegionCustomerID  
    INNER JOIN OrderItem ord ON Cust.MasterCustomerID = ord.MasterCustomerID  
    INNER JOIN Product ON ord.ProductID = Product.ProductID  
    INNER JOIN rootcte rc ON ord.RootOrderId = rc.Rootid   
    INNER JOIN MFolder mf ON mf.mfolderid = rc.itemid  
    INNER JOIN MVersion mv ON mv.mfolderversionid = mf.mfolderid   
    WHERE ord.IsActive = 1  and product.IsSelling = 1 and mf.fileid in (23,45,29)
     and mv.isdeleted = 'N' 

また、BIグループと連携して、クエリロジックを変更し、結合と条件のカップルの移動のcte自体のデータをフィルター処理します。すべてのコメントに感謝します。


2
なぜすべての階層が必要なのですか?どこかにclasueはどこにもないので、使用するレコードだけを計算します。確かに、これを実行するたびに何百万もの階層を構築する必要はありません。
HLGEM

これは、営業時間内に約5〜6回実行され、データセット全体で実行する必要がある付帯レポートです。データが静的であるか、頻繁に挿入されない場合は、データをプリロードすることができますが、この場合、DB内のこのテーブルで頻繁なDML操作が実行されています。
njvds

このテーブルにはどのインデックスがありますか?
ypercubeᵀᴹ

ItemIDは主キーであり、itemidとrootidにも非クラスター化インデックスがあります。
njvds

1
実際に使用しているクエリを表示する必要があります。現在のように、行うことはすべて、テーブルからすべてのItemIDを返す複雑な方法です。再帰CTEは値を追加しません。
ミカエルエリクソン

回答:


3

階層が変更されると言います。おそらくこの操作の実行中に、その時点で行われているブロッキングがいくらかありますか?

階層が変わっても、アイテムのルーツは変わりますか?

ルートからアイテムへのマッピングテーブルを作成してインデックスを作成するのにかかる時間を見ましたか?

実行プランを見て、何が起こっているのかを確認したいと思います。CTEはスプールされるはずですが、手動でマテリアライズされ、インデックスが付けられたテーブルとして、後の手順でパフォーマンスが向上する可能性があります。

アクティビティが重い場合でも、このプロセスが読み取っているデータをDML操作が変更している場合、誰かをブロックする必要があるように思えます。

したがって、階層のスナップショットを取ることを強く検討します。

さらに、他にも多数のINNER JOINがあります。それが実際にCTEであるかどうか、およびこれらの結合を有効にするために欠落しているインデックスがないかどうかを確認する必要があります。実行計画はそれを教えてくれるはずです。

一部の操作を削減するのに役立つ可能性がある(そしてどのインデックスが最適であるかを判断する)WHERE句にかなりの数のものが含まれているように見えますが、実行プランまたはインデックスを見ない限り、判別するのは困難です。


DML操作がSELECTをブロックするのはなぜですか?SQL Serverはまだ制限されていますか?
a_horse_with_no_name 2012

@a_horse_with_no_name msdn.microsoft.com/en-us/library/ms173763.aspx可能ですが、ユーザーはアクティビティが多いため、戦略を考慮する必要があります
Cade Roux
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.