1

テーブルへのマージのソースとして使用したい複雑なクエリがあります。これは、数百万行にわたって実行されます。現在、マージ前に一時テーブルにデータを挿入して、データに制約を適用しようとしています。

操作は次のとおりです。

  • 重複データを除外します。
  • いくつかのテーブルを結合して、追加のデータを取得します
  • 一時テーブルに挿入します。

これがクエリです。

-- Get all Orders that aren't in the system
WITH Orders AS
(
    SELECT *
    FROM [Staging].Orders o
    WHERE NOT EXISTS
    (
        SELECT 1
        FROM Maps.VendorBOrders vbo
        JOIN OrderFact of
        ON of.Id = vbo.OrderFactId
        AND InternalOrderId = o.InternalOrderId
        AND of.DataSetId = o.DataSetId
        AND of.IsDelete = 0
    )
)
INSERT INTO #VendorBOrders
    (
      CustomerId
     ,OrderId
     ,OrderTypeId
     ,TypeCode
     ,LineNumber
     ,FromDate
     ,ThruDate
     ,LineFromDate
     ,LineThruDate
     ,PlaceOfService
     ,RevenueCode
     ,BillingProviderId
     ,Cost
     ,AdjustmentTypeCode
     ,PaymentDenialCode
     ,EffectiveDate
     ,IDRLoadDate
     ,RelatedOrderId
     ,DataSetId
    )
SELECT
     vc.CustomerId
    ,OrderId
    ,OrderTypeId
    ,TypeCode
    ,LineNumber
    ,FromDate
    ,ThruDate
    ,LineFromDate
    ,LineThruDate
    ,PlaceOfService
    ,RevenueCode
    ,bp.Id
    ,Cost
    ,AdjustmentTypeCode
    ,PaymentDenialCode
    ,EffectiveDate
    ,IDRLoadDate
    ,ro.Id
    ,o.DataSetId
FROM
Orders o
-- Join related orders to match orders sharing same instance
JOIN Maps.VendorBRelatedOrder ro
ON ro.OrderControlNumber = o.OrderControlNumber
AND ro.EquitableCustomerId = o.EquitableCustomerId
AND ro.DataSetId = o.DataSetId
JOIN BillingProvider bp
ON bp.ProviderNPI = o.ProviderNPI
-- Join on customers and fail if the customer doesn't exist
LEFT OUTER JOIN [Maps].VendorBCustomer vc
ON vc.ExtenalCustomerId = o.ExtenalCustomerId
AND vc.VendorId = o.VendorId;

時間を最適化するために何かできることはないかと考えています。DB Engine Tuner を使用してみましたが、このクエリは実行中の他のクエリよりも 100 倍多くの CPU 時間を必要とします。他に調査できること、またはクエリをさらに改善できないことはありますか?

4

2 に答える 2

1

CTEは単なる構文です

その CTE はその結合で評価 (実行) されます

まず、選択ステートメントとして実行します(挿入なし)

選択が遅い場合:
その CTE を #TEMP に移動して、1 回評価されて実体化されるよう
にする 3 つの結合列にインデックス (該当する場合は PK) を配置する

選択が遅くない場合は、#VendorBOrders の挿入時間です 最初に
PK のみを作成し、そのクラスター化されたインデックスを断片化しないように PK で挿入を並べ替えます
次に、挿入が完了したら、他の必要なインデックスを構築します

于 2013-04-10T19:17:40.043 に答える
1

通常、速度テストを行うときは、SQL の一部をチェックして、問題がどこにあるかを確認します。「実行計画」をオンにして、多くの時間が費やされている場所を確認します。また、手早く汚いことをしたい場合は、CTEを強調表示して、それを実行してください。それは速いですか、はい、先に進みます。

私は時々、単一のインデックスがオフになっていると、データベースに大きなものの一部を実行させてからその部分を見つけるだけで、結合の複雑なロジック全体がスローされることに気づきました。

もう 1 つのアイデアは、実稼働環境などに高速な tempdb がある場合は、CTE を一時テーブルにもダンプすることです。それにインデックスを付けて、それがスピードアップするかどうかを確認してください。CTE、テーブル変数、および一時テーブルは、結合時にパフォーマンスが低下することがあります。部分的なオブジェクトにインデックスを作成するとパフォーマンスが向上する場合がありますが、これを行うために tempdb により多くの負荷をかけることにもなるので、その点に注意してください。

于 2013-04-10T16:29:07.303 に答える