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

Oracleにスクリプトを介して挿入するより速い方法は?

    問題

    特定のタイプのステートメント、特にINSERT ALLを使用すると、解析時間が指数関数的に増加する場合があります。 。例:

    --Clear any cached statements, so we can consistently reproduce the problem.
    alter system flush shared_pool;
    alter session set sql_trace = true;
    
    --100 rows
    INSERT ALL
        INTO FileIds(Id,FileTypeGroupId) VALUES(1, 1)
        ...
        repeat 100 times
        ...
    select * from dual;
    
    --500 rows
    INSERT ALL
        INTO FileIds(Id,FileTypeGroupId) VALUES(1, 1)
        ...
        repeat 500 times
        ...
    select * from dual;
    
    alter session set sql_trace = false;
    

    tkprofを介してトレースファイルを実行すると、多数の行で解析時間が劇的に増加することがわかります。例:

    100行:

    call     count       cpu    elapsed       disk      query    current        rows
    ------- ------  -------- ---------- ---------- ---------- ----------  ----------
    Parse        1      0.06       0.05          0          1          0           0
    Execute      1      0.00       0.00          0        100        303         100
    Fetch        0      0.00       0.00          0          0          0           0
    ------- ------  -------- ---------- ---------- ---------- ----------  ----------
    total        2      0.06       0.05          0        101        303         100
    

    500行:

    call     count       cpu    elapsed       disk      query    current        rows
    ------- ------  -------- ---------- ---------- ---------- ----------  ----------
    Parse        1     14.72      14.55          0          0          0           0
    Execute      1      0.01       0.02          0        502       1518         500
    Fetch        0      0.00       0.00          0          0          0           0
    ------- ------  -------- ---------- ---------- ---------- ----------  ----------
    total        2     14.74      14.58          0        502       1518         500
    

    ソリューション

    1. 大きなステートメントをいくつかの小さなステートメントに分割します。最適なサイズを見つけるのは難しいです。 Oracleの一部のバージョンでは、問題の原因となる魔法の数の行があります。私は通常、約100行を使用します。これは、ステートメントのグループ化の利点のほとんどを得るのに十分ですが、解析のバグを回避するのに十分な低さです。または...
    2. insert into ... select ... from dual union all ...を試してください 代わりにメソッド。通常ははるかに高速に実行されますが、解析パフォーマンスもサイズによって大幅に低下する可能性があります。
    3. Oracleをアップグレードします。新しいバージョンでは、解析パフォーマンスが向上しています。バージョン12.2ではこの問題を再現できなくなりました。

    警告

    これから間違った教訓を学ばないでください。 SQLのパフォーマンスが心配な場合は、99%の場合、類似したものを分割するのではなく、グループ化する方がよいでしょう。あなたは正しい方法で物事をやっています、あなたはただ奇妙なバグに遭遇しました。 (My Oracle Supportを検索しましたが、これに関する公式のバグは見つかりませんでした。)




    1. SQL Serverの削除ステートメント:テーブルから1つまたは複数の行を削除する方法

    2. 破損したTOASTテーブルの修正

    3. MariaDBでのINSTR()のしくみ

    4. ONUPDATEで次のORA-00907エラーが発生する