0

最近問題が発生しているストアド プロシージャがあり、最終的に 1 つの SELECT に絞り込みました。問題は、この 1 つのクエリのパフォーマンスを低下させるために何が起こっているのかを正確に把握できないことです。書き直しましたが、書き直したものがまったく同じデータかどうかはわかりません。

元のクエリ:

SELECT 
    @userId, p.job, p.charge_code, p.code
, (SELECT SUM(b.total) FROM dbo.[backorder w/total] b WHERE b.ponumber = p.ponumber AND b.code = p.code)
, ISNULL(jm.markup, 0)
, (SELECT SUM(b.TOTAL_TAX) FROM dbo.[backorder w/total] b WHERE b.ponumber = p.ponumber AND b.code = p.code)
, p.ponumber
, p.billable
, p.[date]
FROM dbo.PO p
INNER JOIN dbo.JobCostFilter jcf 
    ON p.job = jcf.jobno AND p.charge_code = jcf.chargecode AND jcf.userno = @userId
LEFT JOIN dbo.JobMarkup jm
    ON jm.jobno = p.job
    AND jm.code = p.code
LEFT JOIN dbo.[Working Codes] wc
    ON p.code = wc.code
INNER JOIN dbo.JOBFILE j
    ON j.JOB_NO = p.job
WHERE (wc.brcode <> 4 OR @BmtDb = 0)
GROUP BY p.job, p.charge_code, p.code, p.ponumber, p.billable, p.[date], jm.markup, wc.brcode

このクエリは実質的に実行を終了しません。私たちが持っているいくつかの大規模なジョブでは、実際にはタイムアウトになります。

そして、select の 2 つのサブクエリを、代わりに結合のように読み取るように変更すると、次のようになります。

SELECT
    @userid, p.job, p.charge_code, p.code
    , (SELECT SUM(b.TOTAL))
    , ISNULL(jm.markup, 0)
    , (SELECT SUM(b.TOTAL_TAX))
    , p.ponumber, p.billable, p.[date]
FROM dbo.PO p
INNER JOIN dbo.JobCostFilter jcf 
    ON p.job = jcf.jobno AND p.charge_code = jcf.chargecode AND jcf.userno = 11190030
INNER JOIN [BACKORDER W/TOTAL] b
    ON P.PONUMBER = b.ponumber AND P.code = b.code
LEFT JOIN dbo.JobMarkup jm
    ON jm.jobno = p.job
    AND jm.code = p.code
LEFT JOIN dbo.[Working Codes] wc
    ON p.code = wc.code
INNER JOIN dbo.JOBFILE j
    ON j.JOB_NO = p.job
WHERE (wc.brcode <> 4 OR @BmtDb = 0)
GROUP BY p.job, p.charge_code, p.code, p.ponumber, p.billable, p.[date], jm.markup, wc.brcode

データは私とほとんど同じように見えます (全体的に数千行あるので間違っている可能性があります)。

どんなアイデアでも大歓迎..

4

2 に答える 2

2
  • パフォーマンス

2 番目のクエリでは、テーブル [BACKORDER W/TOTAL] が 1 回しかスキャンされていないため、論理読み取りが少なくなります。最初のクエリでは、2 つの別個のサブクエリが独立して処理され、テーブルは 2 回スキャンされますが、両方のサブクエリの述語は同じです。

  • 正しさ

2 つのクエリが同じ結果セットを返すかどうかを確認したい場合は、EXCEPT 演算子を使用できます。

両方のステートメントの場合:

最初の SELECT クエリ... EXCEPT 2 番目の SELECT クエリ...

2 番目の SELECT クエリ.. EXCEPT 最初の SELECT クエリ...

結果セットが同一である空のセットを返します。

于 2013-02-22T23:44:01.143 に答える