1

作業中のクエリがあり、予期しないパフォーマンスの問題が表示されています。これまでのクエリは次のとおりです。

INSERT INTO @Bridge (PolicyNumber, ProducerCode, BridgeDate, EffectiveDate, FirstName, LastName, LicenseNumber, BirthDate, Address, City, State, ZipCode)
SELECT     tab.col.value('@PolicyNumber', 'VARCHAR(10)') AS PolicyNumber,
           tab.col.value('@ProducerCode','VARCHAR(10)') as ProducerCode,
           tab.col.value('@BridgeDate','DATETIME') AS BridgeDate,
           tab.col.value('@EffectiveDate', 'DATETIME') as EffectiveDate,
           tab.col.value('@FirstName', 'VARCHAR(200)') as FirstName,
           tab.col.value('@LastName', 'VARCHAR(200)') as LastName,
           CASE 
              WHEN tab.col.value('@LicenseNumber','VARCHAR(50)') LIKE '%0000%' THEN NULL
              WHEN tab.col.value('@LicenseNumber','VARCHAR(50)') LIKE '%1111%' THEN NULL
              WHEN tab.col.value('@LicenseNumber','VARCHAR(50)') LIKE '%2222%' THEN NULL
              WHEN tab.col.value('@LicenseNumber','VARCHAR(50)') LIKE '%3333%' THEN NULL
              WHEN tab.col.value('@LicenseNumber','VARCHAR(50)') LIKE '%4444%' THEN NULL
              WHEN tab.col.value('@LicenseNumber','VARCHAR(50)') LIKE '%5555%' THEN NULL
              WHEN tab.col.value('@LicenseNumber','VARCHAR(50)') LIKE '%6666%' THEN NULL
              WHEN tab.col.value('@LicenseNumber','VARCHAR(50)') LIKE '%7777%' THEN NULL
              WHEN tab.col.value('@LicenseNumber','VARCHAR(50)') LIKE '%8888%' THEN NULL
              WHEN tab.col.value('@LicenseNumber','VARCHAR(50)') LIKE '%9999%' THEN NULL
              ELSE tab.col.value('@LicenseNumber','VARCHAR(50)')
           END as LicenseNumber,
           tab.col.value('@BirthDate','DATETIME') as BirthDate,
           REPLACE(tab.col.value('@Address1','VARCHAR(300)'), ' APT ',' #') as Address1,
           tab.col.value('@City','VARCHAR(300)') as City,
           tab.col.value('@State','VARCHAR(5)') as State,
           tab.col.value('@ZipCode','VARCHAR(10)') as Zip
FROM       @xml.nodes('//rows/datarow') as tab(col)

SELECT     B.PolicyNumber, 
           B.ProducerCode, 
           B.BridgeDate,
           B.EffectiveDate,
           H.current_policy,
           H.cancel_date,
           H.first_eff_date,
           H.display_address,
           H.city,
           H.state,
           H.zip
FROM       @Bridge B
LEFT JOIN  (
SELECT     P.policy_id,
           P.current_policy,
           CASE 
              WHEN A.pobox <> '' THEN 'PO BOX ' + REPLACE(A.pobox,'PO BOX ','')
              ELSE RTRIM(A.house_num + ' ' + A.street_name + ' ' + CASE
                                                                      WHEN A.apt_num = '' THEN ''
                                                                      ELSE '#' + A.apt_num
                                                                    END)
           END as display_address,
           A.pobox,
           A.house_num,
           A.street_name,
           A.apt_num,
           A.city,
           MAX(A.policyimage_num) as policimage_num, --this is just to limit the results to the most recent
           S.state,
           A.zip,
           P.first_eff_date,
           P.cancel_date
FROM       Diamond.dbo.Policy P WITH (NOLOCK)
LEFT JOIN  Diamond.dbo.Address A WITH (NOLOCK)
ON         P.policy_id = A.policy_id
AND        A.nameaddresssource_id = 3
LEFT JOIN  Diamond.dbo.State S WITH (NOLOCK)
ON         A.state_id = S.state_id
WHERE      A.state_id IS NOT NULL
AND        P.current_policy NOT IN (SELECT PolicyNumber FROM @Bridge)
GROUP BY   P.policy_id,
           P.current_policy,
           P.cancel_date,
           P.first_eff_date,
           A.pobox,
           A.house_num,
           A.street_name,
           A.apt_num,
           A.city,
           S.state,
           A.zip) AS H
ON         B.Address = H.display_address
AND        B.State = H.state
AND        B.City = H.city
AND        SUBSTRING(B.ZipCode,1,5) = SUBSTRING(H.Zip,1,5)
AND        B.PolicyNumber != H.current_policy
WHERE      H.current_policy IS NOT NULL

このクエリは単独で実行され、約 1:30 秒で終了します。しかし、WHERE句に次を追加すると

AND       B.EffectiveDate != H.first_eff_date

突然、クエリが結果を返すのに非常に長い時間がかかります。(15 分以上経っていますが、これを書いている間もまだ続きます) いくつかの追加行を除外する節を単に持つだけでは、それほど劇的な効果はないと思いますが、明らかに効果があります。私はそれをどのように回避するか、なぜこの効果があるのか​​について誰かが何か考えを持っているかどうか興味がありますか?

4

1 に答える 1

0

実際に手を動かしていないので推測するしかありませんが、整理しておそらく実行時間を短縮できると思われる場所をいくつか示します。

1、ポリシー番号が一致しないことを確認するために必要な作業を繰り返します。両方ではなく、あなたが持っている2つのうちの1つを選んでください。両方を試して、どちらが速いかを確認することをお勧めします。

すなわちこれ:

AND        P.current_policy NOT IN (SELECT PolicyNumber FROM @Bridge)

これと同じことを行います。両方は必要ありません。

AND        B.PolicyNumber != H.current_policy

2、サブクエリからそのグループ化をすべて削除してみる価値があります-実際にpolicimage_numは何にも使用していません。では、なぜグループ化を行うのでしょうか。多くの行が Address から返されることが心配な場合は、代わりに列セットで DISTINCT を使用できます。その方が高速な場合があります。

3, A.state_id は null 許容値ですか? そうでない場合は、INNER JOIN を Address に試行し、null チェックを削除することを検討してください。

4、正直なところ、そのサブクエリの明確な理由はまったくわかりません。問題を複雑にしすぎているようです。それなしで単純にテーブルを結合することはできませんか (必要に応じて DISTINCT を再度使用します)。

これらのアイデアをいくつか試してみれば、元の実行時間を下回ることができるに違いありません。

于 2013-07-25T14:32:25.713 に答える