2016-11-09 6 views
0

パフォーマンス上の問題を初めて抱えています。だから、私のアプローチが何をすべきかはわかりません。ハッシュ照合右外部結合でSQL Serverのパフォーマンスの問題を改善する方法

これは実行に7分以上かかるクエリです。

INSERT INTO SubscriberToEncounterMapping(PatientEncounterID, InsuranceSubscriberID) 
    SELECT 
     PV.PatientVisitId AS PatientEncounterID, 
     InsSub.InsuranceSubscriberID 
    FROM 
     DB1.dbo.PatientVisit PV 
    JOIN 
     DB1.dbo.PatientVisitInsurance PVI ON PV.PatientVisitId = PVI.PatientVisitId 
    JOIN 
     DB1.dbo.PatientInsurance PatIns on PatIns.PatientInsuranceId = PVI.PatientInsuranceId 
    JOIN 
     DB1.dbo.PatientProfile PP On PP.PatientProfileId = PatIns.PatientProfileId 
    LEFT OUTER JOIN 
     DB1.dbo.Guarantor G ON PatIns.PatientProfileId = G.PatientProfileId 
    JOIN 
     Warehouse.dbo.InsuranceSubscriber InsSub ON InsSub.InsuranceCarriersID = PatIns.InsuranceCarriersId 
         AND InsSub.OrderForClaims = PatIns.OrderForClaims 
         AND ((InsSub.GuarantorID = G.GuarantorId) OR (InsSub.GuarantorID IS NULL AND G.GuarantorId IS NULL)) 
    JOIN 
     Warehouse.dbo.Encounter E ON E.PatientEncounterID = PV.PatientVisitId  

実行計画は

ハッシュマッチ右外側はそのコスト89%、クエリの

に参加していると述べています。

enter image description here

右外側には、問題がどこにあるか私は見ていないので、クエリに参加ありません。

クエリをより効率的にするにはどうすればよいですか? enter image description here

+0

まず:Guarantorから私は、あなたが.....また、列のあなたの 'SELECT'リストに使用' InsSub'エイリアスを使用して、あなたの文で任意のテーブルが表示されない:あなたを行います*本当に*この2つの情報だけを得るためには、すべてのテーブルに参加する必要がありますか? –

+0

ハッシュ一致の詳細を表示できますか?プローブとは何ですか、出力は何ですか?スクリーンショットからは明らかではありません。私は、この述語があなたの問題を引き起こしていると推測します。 '(InsSub.GuarantorID = G.GuarantorId)OR(InsSub.GuarantorID IS NULLとG.GuarantorId IS NULL)'では、2つのクエリを使用して、このような 'OR'述部があると、最適ではない計画になり、2つの別々の照会が索引をよりうまく利用できるようになります。 – GarethD

+0

@GarethDおそらく、where節でEXISTSを使用するのではなく、joinの2つの述語を使うのでしょうか? – dfundako

答えて

1

は、あなたがそれをInsuranceSubscriberNULLときに一致させるために、最初はGuarantorIDおよび第二に一致する2つのクエリにそれを分割しようとすることができ、私のコメントについて詳しく説明し、Guarantorで、またはレコードが完全に欠落している場合には、すべての

INSERT INTO SubscriberToEncounterMapping(PatientEncounterID, InsuranceSubscriberID) 
SELECT PV.PatientVisitId AS PatientEncounterID, InsSub.InsuranceSubscriberID 
FROM DB1.dbo.PatientVisit PV 
     JOIN DB1.dbo.PatientVisitInsurance PVI 
      ON PV.PatientVisitId = PVI.PatientVisitId 
     JOIN DB1.dbo.PatientInsurance PatIns 
      ON PatIns.PatientInsuranceId = PVI.PatientInsuranceId 
     JOIN DB1.dbo.PatientProfile PP 
      ON PP.PatientProfileId = PatIns.PatientProfileId 
     JOIN DB1.dbo.Guarantor G 
      ON PatIns.PatientProfileId = G.PatientProfileId 
     JOIN Warehouse.dbo.InsuranceSubscriber InsSub 
      ON InsSub.InsuranceCarriersID = PatIns.InsuranceCarriersId 
      AND InsSub.OrderForClaims = PatIns.OrderForClaims 
      AND InsSub.GuarantorID = G.GuarantorId 
     JOIN Warehouse.dbo.Encounter E 
      ON E.PatientEncounterID = PV.PatientVisitId 
UNION ALL 
SELECT PV.PatientVisitId AS PatientEncounterID, InsSub.InsuranceSubscriberID 
FROM DB1.dbo.PatientVisit PV 
     JOIN DB1.dbo.PatientVisitInsurance PVI 
      ON PV.PatientVisitId = PVI.PatientVisitId 
     JOIN DB1.dbo.PatientInsurance PatIns 
      ON PatIns.PatientInsuranceId = PVI.PatientInsuranceId 
     JOIN DB1.dbo.PatientProfile PP 
      ON PP.PatientProfileId = PatIns.PatientProfileId 
     JOIN Warehouse.dbo.InsuranceSubscriber InsSub 
      ON InsSub.InsuranceCarriersID = PatIns.InsuranceCarriersId 
      AND InsSub.OrderForClaims = PatIns.OrderForClaims 
      AND InsSub.GuarantorID IS NULL 
     JOIN Warehouse.dbo.Encounter E 
      ON E.PatientEncounterID = PV.PatientVisitId 
WHERE NOT EXISTS 
     ( SELECT 1 
      FROM DB1.dbo.Guarantor G 
      WHERE PatIns.PatientProfileId = G.PatientProfileId 
      AND  InsSub.GuarantorID IS NOT NULL 
     ); 
+0

これは間違いなく高速です。しかし、返されたレコードは元のクエリと同じではありません。だからtweekする必要がありますが、これは間違いなく行く方法です!.THANKS! –

-2

インクルードが参加し、各によって返されるレコードの数を減少させる能力に基づいて結合が、私は考え直すため:ここ

は、ハッシュマップの詳細です。いずれの結合でも数値を減らすことができ、返されたレコードは効率を向上させます。次に、外部結合を実行します。また、テーブルのロックは常に問題になる可能性がありますので、ロックされているレコードを防ぐために(nolock)を追加してください。

多分このようなものは、少し微調整しても機能します。

INSERT INTO SubscriberToEncounterMapping (
    PatientEncounterID 
    , InsuranceSubscriberID 
    ) 
SELECT PV.PatientVisitId AS PatientEncounterID 
    , InsSub.InsuranceSubscriberID 
FROM DB1.dbo.PatientVisit PV WITH (NOLOCK) 
INNER JOIN Warehouse.dbo.Encounter E WITH (NOLOCK) 
    ON E.PatientEncounterID = PV.PatientVisitId 
INNER JOIN DB1.dbo.PatientVisitInsurance PVI WITH (NOLOCK) 
    ON PV.PatientVisitId = PVI.PatientVisitId 
INNER JOIN DB1.dbo.PatientInsurance PatIns WITH (NOLOCK) 
    ON PatIns.PatientInsuranceId = PVI.PatientInsuranceId 
INNER JOIN DB1.dbo.PatientProfile PP WITH (NOLOCK) 
    ON PP.PatientProfileId = PatIns.PatientProfileId 
INNER JOIN Warehouse.dbo.InsuranceSubscriber InsSub WITH (NOLOCK) 
    ON InsSub.InsuranceCarriersID = PatIns.InsuranceCarriersId 
     AND InsSub.OrderForClaims = PatIns.OrderForClaims 
LEFT JOIN DB1.dbo.Guarantor G WITH (NOLOCK) 
    ON PatIns.PatientProfileId = G.PatientProfileId 
     AND (
      (InsSub.GuarantorID = G.GuarantorId) 
      OR (
       InsSub.GuarantorID IS NULL 
       AND G.GuarantorId IS NULL 
       ) 
      ) 
+1

NOLOCKを追加すると、実行計画にハッシュ結合演算子がどのように影響しますか? – dfundako

+1

結合が書き込まれる順序は、(OPTION(FORCEORDER)を使用しない限り)実行される順序には無関係です。したがって、これは何の違いもありません。 [悪い習慣:どこにでもNOLOCKを置く](https://blogs.sentryone.com/aaronbertrand/bad-habits-nolock-everywhere/)も読んでみてください。魔法のパフォーマンスの修正ではありませんので、注意して使用してください通常は理解し、リスクを認識している人によって行われます。 – GarethD

+0

私は結合順序が重要であることを発見しました。オプティマイザがジョインするためにオプティマイザを信頼するようにしたいのであれば、それはうまくいくか、自分で最適化します。Joins。合意したロックは必要ないか、理想的ではないかもしれませんが、何かがロックしていると、ロックを待たずに実行を速くします。削除しても問題が解決しない場合。ハッシュ・マッチは常にそこにありますが、操作のレコード・セット・サイズを小さくすれば助けになります。 – KH1229