sql >> データベース >  >> RDS >> Oracle

Oracleで10分以内に1,000万のクエリを挿入しますか?

    他の人がこれについて言及していることは知っていますが、聞きたくないのですが、SQL*Loaderまたは外部テーブルを使用してください。ほぼ同じ幅のテーブルの平均読み込み時間は12.57です。 10mを少し超える行の場合。これらのユーティリティは、データベースにデータをすばやくロードするように明示的に設計されており、非常に優れています。入力ファイルの形式によっては、追加の時間ペナルティが発生する場合がありますが、かなりの数のオプションがあり、ロードする前にファイルを変更する必要はほとんどありません。

    これを実行したくない場合は、ハードウェアをまだアップグレードする必要はありません。これをすばやくロードする際に考えられるすべての障害を取り除く必要があります。それらを列挙するには、以下を削除します:

    1. インデックス
    2. トリガー
    3. シーケンス
    4. パーティション

    これらすべてを使用すると、データベースにさらに多くの作業を実行する義務があり、これをトランザクションで実行しているため、データベースを最大限に活用していません。

    ABC_LOADなどの別のテーブルにデータをロードします 。データが完全に読み込まれた後、シングルを実行します ABCにステートメントを挿入します。

    insert into abc
    select abc_seq.nextval, a.*
      from abc_load a
    

    これを行うとき(そしてそうでない場合でも)、シーケンスキャッシュサイズが正しいことを確認してください。引用する:

    アプリケーションがシーケンスキャッシュ内のシーケンスにアクセスすると、シーケンス番号がすばやく読み取られます。ただし、アプリケーションがキャッシュにないシーケンスにアクセスする場合は、シーケンス番号を使用する前に、シーケンスをディスクからキャッシュに読み取る必要があります。

    アプリケーションが同時に多くのシーケンスを使用する場合、シーケンスキャッシュはすべてのシーケンスを保持するのに十分な大きさではない可能性があります。この場合、シーケンス番号にアクセスするにはディスクの読み取りが必要になることがよくあります。すべてのシーケンスにすばやくアクセスするには、アプリケーションで同時に使用されるすべてのシーケンスを保持するのに十分なエントリがキャッシュにあることを確認してください。

    これは、このシーケンスを使用してそれぞれ500レコードを同時に書き込む10個のスレッドがある場合、5,000のキャッシュサイズが必要であることを意味します。 ALTER SEQUENCEドキュメントには、これを変更する方法が記載されています。

    alter sequence abc_seq cache 5000
    

    私の提案に従えば、キャッシュサイズを約10.5mに増やします。

    APPENDヒントの使用を検討してください(Oracle Baseも参照)。これは、データを配置するスペースを探すのではなく、テーブルの最後に直接データを追加するダイレクトパス挿入を使用するようにOracleに指示します。テーブルにインデックスがある場合はこれを使用できませんが、ABC_LOADで使用できます。

    insert /*+ append */ into ABC (SSM_ID, invocation_id , calc_id, ... )
    select 'c','b',NULL, 'test', 123 , 'N', 'asdf' from dual
    union all select 'a','b',NULL, 'test', 123 , 'N', 'asdf' from dual
    union all select 'b','b',NULL, 'test', 123 , 'N', 'asdf' from dual
    union all select 'c','g',NULL, 'test', 123 , 'N', 'asdf' from dual
    

    APPENDヒントを使用する場合; TRUNCATE ABC_LOADを追加します ABCに挿入した後 そうしないと、このテーブルは無期限に大きくなります。それまでにテーブルの使用を終了するので、これは安全なはずです。

    使用しているバージョンやエディション、またはOracleについては言及していません。使用できる特別なトリックがいくつかあります:

    • Oracle 12c

      このバージョンはID列をサポートしています。シーケンスを完全に取り除くことができます。

      CREATE TABLE ABC(
         seq_no         NUMBER GENERATED AS IDENTITY (increment by 5000)
      
    • Oracle 11g r2

      トリガーを保持する場合;シーケンス値を直接割り当てることができます。

      :new.seq_no := ABC_seq.nextval;
      
    • Oracle Enterprise Edition

      Oracle Enterpriseを使用している場合は、ABC_LOADからINSERTを高速化できます。 PARALLELヒントを使用して:

      insert /*+ parallel */ into abc
      select abc_seq.nextval, a.*
        from abc_load a
      

      これにより、独自の問題(並列プロセスが多すぎるなど)が発生する可能性があるため、テストしてください。 かもしれない 小さなバッチ挿入には役立ちますが、どのスレッドが何を処理するかを計算する時間が失われる可能性が低くなります。

    tl; dr

    データベースに付属のユーティリティを使用します。

    それらを使用できない場合は、挿入の速度を低下させる可能性のあるすべてのものを取り除き、一括で実行してください。これは、データベースが得意とすることだからです。



    1. MySQL CEILING()関数–最も近い整数に切り上げ

    2. Spring + Hibernate:クエリプランのキャッシュメモリ使用量

    3. pdomysqlトランザクションを理解する

    4. PostgreSQLで重複する日付をテストする方法