8

私はオラクルが初めてで、この問題と戦わなければなりません。

内部に約 5 億 2000 万行のテーブルがあります。すべての行をフェッチし、NoSQL データベース内にインポート (非正規化) する必要があります。

このテーブルには、C_ID と A_ID の 2 つの整数フィールドと、C_ID に 1 つ、A_ID に 1 つ、両方のフィールドに 1 つの 3 つのインデックスがあります。

私は最初にこの方法を試しました:

SELECT C_ID, A_ID FROM M_TABLE;

そして、これは妥当な時間内に結果をもたらしたことはありません(完了しないように見えたため、時間を測定する可能性がありませんでした)。

クエリを次のように変更しました。

SELECT /*+ ALL_ROWS */ C_ID, A_ID FROM (SELECT
    rownum rn, C_ID, A_ID
FROM
    M_TABLE WHERE rownum < ((:1 * :2 ) +1 )) WHERE rn >= (((:1 -1) * :2 ) +1 );

3 つのスレッドを使用し、サイズ 1000 のページを使用してページネーションを使用して、このクエリを並行して実行します。

3 つの最適化を導入しようとしました。

1)テーブルの統計を作成しました:

ANALYZE TABLE TABLE_M ESTIMATE STATISTICS SAMPLE 5 PERCENT;

2) テーブルを 8 つのパーティションに分割しました。

3) 並列オプションでテーブルを作成しました。

現在、1 秒あたり 10000 行をフェッチできるため、プロセス全体が完了するまでに約 15 時間かかります (DB は 4 コア、8 GB マシンで実行されています)。

問題は、最大 5 時間ですべてを完了する必要があることです。

私にはアイデアがありません。そのため、新しいマシンを要求する前に、このような状況でパフォーマンスを向上させる方法をご存知ですか。

4

4 に答える 4

5

オラクルは、どこで時間を過ごしたかを私たちに伝えるのに非常に賢いです。これを行うには、Oracleの拡張SQLトレース(つまり、10046トレース)を使用してセッションをトレースします。クエリは、大量のデータを含む1つのテーブルからデータを抽出しています。IOレート(db_file_scattered_read)を確認してください。これは、おそらくクエリの上位の待機イベントの1つです。

それが役に立てば幸い。

于 2013-02-01T15:55:13.740 に答える
5

あなたはあなたの結果をどうしますか?PL/SQL を使用してファイルに直接フェッチされますか、それとも別のアプリケーションを使用してデータを処理しますか? ネットワーク経由で送信されますか? (これは簡単に達成できる成果かもしれません)。

私が尋ねる理由は、通常、FULL SCAN(ORDER BYなしで)最初の行が即座に返されるためです。結果をファイルに出力している場合は、ファイルがすぐにいっぱいになるはずです。そうしない場合、これはセグメントの先頭に多くの空白があることを意味し、クエリが返されない理由を説明できます (少なくとも妥当な時間内に)。

では、クエリが返されないと言うとき、私は少し心配ですが、どうすればわかりますか? 次のブロックは戻りますか?

DECLARE
  l NUMBER := 0;
BEGIN
  FOR cc IN (SELECT C_ID, A_ID FROM M_TABLE) LOOP
    l := l + 1;
    EXIT WHEN l >= 100000;
  END LOOP;
END;

表示される場合は、FULL SCAN が処理されていることを意味します。上記のクエリのタイミングをとることで、セグメントが均一に密集していると仮定して、完全な 1 つの SCAN に必要な時間を計算できるはずです。

5 億行を読み取るのは大変な作業ですが、行は小さいため、テーブル セグメントが適切に圧縮されていれば、Oracle は妥当な時間内にすべての行を返す必要があります。INSERT /*+APPEND*/テーブル セグメントは、たとえば削除とロードを繰り返すと、非効率的な領域構成になる可能性があります。テーブルを再構築 ( ALTER TABLE MOVE) すると、セグメント内の無駄な空き領域がすべて削除されます。ちなみに、テーブルを分割したときに再構築したため、これがクエリが返される理由かもしれません!!

いずれにせよ、おそらくテーブルを再構築して空き領域と最高水準点をリセットした後に、FULL TABLE SCAN を再試行することをお勧めします。単一の FULL TABLE SCAN は、大量のデータにアクセスするための最も信頼性の高い (そして最も効率的な) 方法の 1 つです。

パフォーマンスをさらに向上させる必要がある場合は、ROWID パーティショニング ( DIY 並列処理スキーム) または組み込みパッケージを検討することをお勧めしますDBMS_PARALLEL_EXECUTE

于 2013-02-01T16:47:51.163 に答える
2

試すのは少し抜本的な解決策かもしれませんが、テーブルの圧縮を見ることができます。Oracle 10g では、書き込み操作が行われるとブロックが圧縮解除されるため、これは読み取り専用テーブルにのみ役立ちます。データ ウェアハウス環境の大きなテーブルには、圧縮が役立つことがわかりました。

特定のパーティションのみを圧縮することもできるため、日付でパーティション分割されたテーブルの末尾にデータを追加する場合、最新のパーティションを圧縮せずに履歴パーティションを圧縮することができます。

テーブル圧縮の利点は、必要な I/O の量を削減できることです。これは、I/O に制約のあるシステムで役立つ可能性があります。テーブルに何が格納されているか、およびデータを挿入するときに使用される並べ替えに依存しますが、テーブルから 10:1 の圧縮が得られることがよくありました。

既存のテーブルの場合、次のコマンドを使用できると思います。

ALTER TABLE M_TABLE COMPRESS MOVE;

これは問題を解決するのに役立つかもしれませんが、テーブルの基礎となる構造を変更すると少し劇的になる可能性があることに注意してください。また、テーブルを圧縮して再構築すると、一部のインデックスが無効になる可能性があります。

Oracle 11g では、データの更新を可能にする高度な圧縮も可能ですが、これには高価なライセンス コストがかかります。

ここにはいくつかのドキュメントがあり、この PDF ドキュメントにはさらに多くの情報があります

于 2013-02-01T23:06:46.433 に答える
1

はい、user2033072 が言ったように、クエリについてもう少し知っておく必要がSQL Traceあります。公式ドキュメントTkProfを見ることができます。

また、より簡単に を使用することもできますexplain plan。そのようにすると、Oracle は何を計画しているかを表示します。

于 2013-02-01T16:01:57.077 に答える