web-dev-qa-db-ja.com

CASE WHEN EXISTSサブクエリ最適化を使用したOracle SQLクエリ

Oracle 11g(11.2.0.3.0)でビューを作成するために次のクエリを使用しています。

CREATE OR REPLACE FORCE VIEW V_DOCUMENTS_LIST
(
   ID_DOC,
   ATTACHMENTS_COUNT,
   TOTAL_DIMENSION,
   INSERT_DATE,
   ID_STATE,
   STATE,
   ID_INSTITUTE,
   INSTITUTE,
   HASJOB
)
AS
    SELECT D.ID_DOC,
        COUNT (F.ID_FILE) AS ATTACHMENTS_COUNT,
        CASE
           WHEN SUM (F.DIMENSION) IS NULL THEN 0
           ELSE SUM (F.DIMENSION)
        END
           AS TOTAL_DIMENSION,
        D.INSERT_DATE,
        D.ID_STATE,
        S.STATE_DESC AS STATE,
        D.ID_INSTITUTE,
        E.NAME AS INSTITUTE,
        CASE
           WHEN EXISTS (SELECT D.ID_DOC FROM JOB) THEN 'true'
           ELSE 'false'
        END
           AS HASJOB
    FROM DOCUMENTS D
        LEFT JOIN FILES F ON D.ID_DOC = F.ID_DOC
        JOIN STATES S ON D.ID_STATE = S.ID_STATE
        JOIN INSTITUTES E ON D.ID_INSTITUTE = E.ID_INSTITUTE
    GROUP BY D.ID_DOC,
        D.INSERT_DATE,
        D.ID_STATE,
        S.STATE_DESC,
        D.ID_INSTITUTE,
        E.NAME;

次に、そのビューをクエリして、DataGridViewページのASPXの値を取得します。

SELECT * 
FROM V_DOCUMENTS_LIST
ORDER BY ID_STATE DESC, INSTITUTE, INSERT_DATE DESC;

関連するテーブルとリレーション

文書;ファイル; JOBS;

ドキュメント(1-1)<---->(0-N)ファイル

ジョブ(0-1)<---->(0-N)ドキュメント

ビューにクエリを実行すると、関連するすべての情報(ID、説明、日付、状態など)を含むドキュメントの完全なリストと、それぞれのリストが表示されます。

  • 添付ファイルの総数;
  • 添付ファイルのバイト単位の合計寸法;
  • 少なくとも1つあるかどうかを示すブール値JOBに関連付けられているDOCUMENTまたはない

ビューに数千のレコードが含まれるまで、すべてがうまくいきました。これで、レコードの量が増加し、SELECT * FROMビューの所要時間は約2:30分で、15,000〜20.000レコードです。私のビューの本当に時間がかかる部分はネストされたSELECTであることを知っています:

CASE
    WHEN EXISTS (SELECT D.ID_DOC FROM JOB) THEN 'true'
    ELSE 'false'
END
AS HASJOB

ビューを最適化するにはどうすればよいですか?

4
Cheshire Cat

存在しない問題に対処するには、結合を追加できます。

LEFT JOIN (select distinct id_doc from JOB) J
ON d.id_doc = J.id_doc

Has_job列は次のようになります。

    CASE
       WHEN j.id_doc is not null THEN 'true'
       ELSE 'false'
    END AS HASJOB

[〜#〜] ps [〜#〜]:ジョブテーブルに行がある場合、SELECT D.ID_DOC FROM JOBには常に行が含まれるため、現在の実装には問題があります。存在する行をテストするだけなので、select * from jobと同じです。論理的に正しい実装はSELECT 1 FROM JOB j where j.id_doc = D.ID_DOCです。

5
Florin Ghita

テーブルJOBに完全なインデックスを作成し、WHERE句をクエリに挿入します。

SELECT D.ID_DOC FROM JOB
0
Iffo