1

2つのアプリケーションがあります。最初のアプリケーションはテーブルMyTableにデータを挿入します。2つ目は、テーブルMyTableの行をチャンクで読み取ります。たとえば、読み取りごとに1000行とします。この2番目のアプリは、データを時系列で読み取り、次のようなクエリを使用する必要があります。

SELECT
    C1,
    C2
FROM
(
    SELECT
        rownum AS RowNumber, 
        C1, 
        C2
    FROM
        MyTable
    WHERE
        C3 = :C3
        AND IsProcessed = 0
    ORDER BY
        Timestamp
) temp 
WHERE 
    temp.RowNumber <= 1000

クエリは機能しますが、処理されていない行が多数(たとえば、1,000万)テーブルMyTableで待機している場合は、処理が遅くなります(1分以上、通常は実行に数秒しかかかりません) 。Oracleは最初に関連するすべての行を時系列で並べ替える必要があるため、これは正常だと思います...したがって、私の質問は次のとおりです。このクエリを作成するためのより良い方法はありますか?

ここに画像の説明を入力してください

4

3 に答える 3

1

あなたの実行計画から、あなたの述語C3 = :C3はかなり高価だと思います。RAWタイプを避けて、それを最適化するようにしてください。いくつかのオプションがあります:

  • インデックスがあることを確認してくださいSUBCONTRACTID
  • に関数ベースのインデックスを追加してみてくださいNVL(BUSINESSTRANSACTIONID, HEXTORAW('00'))
  • インデックスがあることを確認し、ではなく、BUSINESSTRANSACTIONIDを使用してクエリを実行しますIS NULLNVL(...)
  • 根底にあるビジネス要件を緩和できれば、もちろん、ORDER BY timestamp条項を削除してレコードを任意の順序で処理するのに役立ちます。

それとは別に、クエリは問題ないようです。

また、ヒントを適用してみてください。これは、フィルタリング/*+FIRST_ROWS(1000)*/を使用しても、クエリで何らかの理由で自動的に行われないようです。ROWNUM

于 2012-08-13T17:37:17.203 に答える
0

RowNumber の列を定義する必要はありません。

SELECT C1, C2 
FROM (
   SELECT C1, C2     
   FROM   MyTable
   WHERE  C3 = :C3
      AND IsProcessed = 0
   ORDER BY Timestamp 
   ) temp
WHERE ROWNUM <= 1000

「より速く」する唯一の方法は、派生テーブルのサイズを何らかの形でさらに制限することです。

于 2012-08-13T17:13:03.960 に答える
0
SELECT * FROM
  (    SELECT C1, C2
      FROM MyTable
     WHERE C3 = :C3
       AND IsProcessed = 0
     ORDER BY Timestamp
  ) WHERE rownum <= 1000;

このクエリを試してください。

于 2012-08-13T16:57:19.683 に答える