0

アプリケーションで、異なる基準に一致するデータの数を表示する状況があります。データベースの成長に対してカウントのパフォーマンスが低下しているため、exists 句を使用して可用性情報のみを表示することにしました。

以下は私のテーブル構造です

Table: DocInfo
---------------------------------------
DocId       number
DocName     varchar(250)
DocStatus   number
SignedBy    number
ForwardedBy number
ForwardCount    number
DocOwner    number
MgrID       number
ProjectId   number

カウントを行う現在のクエリは次のようになります

SELECT NVL(SUM(CASE
                 WHEN (DocStatus IN (1150,1155,1170,1182,1190) AND
                       DocOwner=56366 AND
                       ForwardCount=0)
                   THEN 1
                   ELSE 0
               END), 0) "ForReview",
       NVL(SUM(CASE
                 WHEN (DocStatus IN (1200) And
                       MgrID = 56366 AND
                       ForwardCount = 0 )
                   THEN 1
                   ELSE 0
               END), 0) "Accepted" , 
       NVL(SUM(CASE
                 WHEN (DocStatus IN (1150,1155,1170,1182,1190) AND
                       DocOwner=56366 AND
                       MgrID = 0 )
                   THEN 1
                   ELSE 0
               END), 0) "Waiting"
  FROM DocInfo 
  WHERE ProjectId = 313 and
        (DocOwner = 56366 or MgrID = 56366)

existsドキュメントが各カテゴリで利用可能かどうかを示すことができるように、カウントを句に変更する必要があります。

この変更はパフォーマンスを向上させるためのものであるため、これを別のクエリとして実行することもお勧めできません。助けてください、限られた知識を使い果たしました。

すでに試した部分を見逃して申し訳ありません。

上記のクエリを、以下のようにそれぞれに exists 句を含むユニオンに変更しました。

SELECT 'ForReview' AS A
  FROM DUAL
  WHERE EXISTS (SELECT NULL
                  FROM DocInfo 
                  WHERE ProjectId = 313 and
                        (DocOwner = 56366 or MgrID = 56366)  and
                        (DocStatus IN (1150,1155,1170,1182,1190) AND
                         DocOwner=56366 AND
                         ForwardCount=0)) 
UNION 
  SELECT 'Accepted' AS A
    FROM DUAL
    WHERE EXISTS (SELECT NULL
                    FROM DocInfo
                    WHERE ProjectId = 313 and
                          (DocOwner = 56366 or MgrID = 56366) and
                          (DocStatus IN (1200) And
                           MgrID = 56366 AND
                           ForwardCount = 0 )) 
UNION
  SELECT 'Waiting' AS A
    FROM DUAL
    WHERE EXISTS (SELECT NULL
                    FROM DocInfo
                    WHERE ProjectId = 313 and
                          (DocOwner = 56366 or MgrID = 56366) and
                          (DocStatus IN (1150,1155,1170,1182,1190) AND
                           DocOwner=56366 AND
                           MgrID = 0)) 

私は 3 つの条件しか言及していませんが、私の実際のアプリケーションには、このクエリに追加する 8 つの異なる条件があります。したがって、8 つの Exists 句がある場合、8 つの異なるクエリとして内部的に実行され、実際にはより多くの時間がかかります。ユニオン クエリ全体の 1 つのセグメントは 560 ミリ秒しかかかりませんが、すべてのクエリを合わせて出力を生成するには約 7 秒かかります。

私の要件は、そのようなレコードの可用性を識別することだけであるため、レコードセット全体をナビゲートしてカウントしたくありません。

このクエリを最適化/書き換える方法はありますか

ありがとうございました

4

1 に答える 1

3

「したがって、Exists句が8つある場合、内部で8つの異なるクエリとして実行され、実際には時間がかかります。ユニオンクエリ全体の単一セグメントは560ミリ秒しかかかりませんが、すべてのクエリを合わせると出力の生成に約7秒かかります。」

サプライズ、サプライズ。同じクエリに相当するものを8回実行すると、そのクエリを1回実行するよりも速くなることはありません。

データセット全体を取得するのではなく、指定された基準に一致する単一の行を見つけるだけでよいため、EXISTSの方が高速になる可能性があるのは事実です。ただし、取得したデータをWHERE句にシフトしたばかりなので、データベースは同じ量の作業を実行する必要があります。実際、それは明らかにもっと多くの仕事をしているようです7s > (560ms * 8)

問題を適切に解決するには、データベースがどのように機能し、どのように調整するかを理解する必要があります。 詳細をご覧ください

まず、チューニングの目標を定義します。元のクエリの実行には0.5秒かかります。これは非常に高速ではありませんが、かなり高速です。なぜこれが問題なのですか?どのくらいの速さで実行しますか?

次に、EXPLAINPLANを実行します。クエリはインデックスを使用していますか?インデックスの使用効率はどれくらいですか>行の何パーセントが選択されていますか?

ここで、データを理解する必要もあります。選択したデータはテーブル全体に均等に分散されていますか、それともクラスターがありますか?一部のプロジェクト、所有者、または管理者は、他のプロジェクトよりも多くのレコードを持っていますか?その分布はパフォーマンスにどのように影響しますか?

チューニングは科学であり、複雑であることに注意してください。このテーマに関する本は全部あり、パフォーマンスのトラブルシューティングとして非常に素晴らしい生活を送っている人もいます。これには、アプリケーションの機能に関する知識と、データベースが実行しているアクティビティに関する低レベルの情報の両方について、システムに関する多くの情報が必要です。私たちはあなたの探求においてよりパフォーマンスの高い解決策を見つけるのを手伝うことができますが、私たちはただひどいクエリを見て、それがより速く実行されるように書き直す方法をあなたに教えることはできません。

于 2012-06-22T11:56:26.873 に答える