0

最近問題が発生しました。Oracle DBからバッチでデータのテーブルを取得したかったのですが、バッチはたとえば4〜5000です。私の以前の「一般的な」解決策は、selectを次のようなものにラップすることでした。

SELECT * FROM (
    SELECT ROWNUM AS RN, INNERSELECT.* FROM (
        select THINGS1, THINGS2 from MYTABLE)
    )
INNERSELECT WHERE ROWNUM < 4001) WHERE RN >= 3001

rownumの境界が高い場合(たとえば、4-500.000)、選択に10〜20秒以上かかるため、遅いように見えます。そして、値を増やすにつれて、時間は直線的に増加しています。もちろん、その理由はわかっているので、データをバッチで取得するための別のソリューションを見つけたいと思いましたが、時間枠は保証されていました。それで、私はこの種の選択を使用しました:

SELECT * FROM (
  SELECT INNERSELECT.*, ROW_NUMBER() OVER (ORDER BY INNERSELECT.ROWID) RN FROM 
    ( select THINGS1, THINGS2 from MYTABLE)
    INNERSELECT
) WHERE RN BETWEEN 3001 AND 4000;

これは少し遅いですが(テスト用のデータのバッチを取得するのに3〜4秒かかりました)、パフォーマンスの低下を目立たせることなくバッチサイズを増やすことができ、高い値でも同じになります。現在の問題は、DBから複数のスレッドの複数のテーブルから選択し、3つのスレッドを使用するとパフォーマンスが低下することです(現在プロジェクトで使用されている16については説明していません)。JDBC接続はプールされ、パフォーマンスの低下はサーバー側にあります。選択がCPU時間を消費しているので、私は何もできないことは明らかだと思いますが、これを最適化するためのヒントを皆さんに知ってもらいたいと思います。

もう1つの問題は、使用するツールがプロジェクト固有ではなく、可能な限り一般的である必要があるため、たとえばコピーテーブルなどを使用できないことです。

事前に回答ありがとうございます

4

2 に答える 2

1

MYTABLEが数値の主キーを持っていると仮定するとID、1つの戦術は、16個のスレッドのそれぞれにこのクエリを実行させることです。

SELECT THINGS1, THINGS2
FROM   MYTABLE
WHERE  MOD(ID,15) = :THREAD_NUMBER

各スレッドは0から15までの一意の値を取得します:THREAD_NUMBER。つまり、各スレッドは(約)行の1/16を取得します。

于 2012-08-06T20:23:57.030 に答える
0
SELECT * FROM (
  SELECT INNERSELECT.*, ROW_NUMBER() OVER (ORDER BY INNERSELECT.ROWID) RN FROM 
    ( select THINGS1, THINGS2 from MYTABLE)
    INNERSELECT
) WHERE RN BETWEEN 3001 AND 4000;

(MYTABLEからTHINGS1、THINGS2を選択します)

これは何行を取得しますか?これに何らかの制限句を配置できる場合は、システムが全表スキャンまたはインデックススキャンを実行する必要がなくなります。

INNERSELECT.ROWIDで注文

この種の発行は必要ですか?特に、ソート基準はシステムによって生成された値であるためです。大規模な並べ替えは、データベースに大きな影響を与える可能性があります。

覚えておくべき重要なことは、OracleでROWNUMを使用してレコードを抽出することです。データベースは、最後のものの1つとして、ただしORDERBYの前にROWNUMをレコードに適用します。

于 2012-08-06T20:03:16.637 に答える