一時テーブルは、キャッシュと非同期I / Oのおかげで、実質的にメモリ内テーブルと同じです。一時テーブルソリューションでは、SQLとPL/SQL間の変換にオーバーヘッドは必要ありません。
結果の確認
2つのバージョンをRunStatsと比較すると、一時テーブルバージョンは見た目 ずっと悪いです。 Run1の一時テーブルバージョンのすべてのジャンクと、Run2のPL/SQLバージョンのわずかな追加メモリ。最初は、PL/SQLが明らかに勝者になるはずです。
Type Name Run1 (temp) Run2 (PLSQL) Diff
----- -------------------------------- ------------ ------------ ------------
...
STAT physical read bytes 81,920 0 -81,920
STAT physical read total bytes 81,920 0 -81,920
LATCH cache buffers chains 104,663 462 -104,201
STAT session uga memory 445,488 681,016 235,528
STAT KTFB alloc space (block) 2,097,152 0 -2,097,152
STAT undo change vector size 2,350,188 0 -2,350,188
STAT redo size 2,804,516 0 -2,804,516
STAT temp space allocated (bytes) 12,582,912 0 -12,582,912
STAT table scan rows gotten 15,499,845 0 -15,499,845
STAT session pga memory 196,608 19,857,408 19,660,800
STAT logical read bytes from cache 299,958,272 0 -299,958,272
しかし、結局のところ、重要なのは壁掛け時計の時間だけです。一時テーブルを使用すると、読み込みとクエリの両方の手順がはるかに高速に実行されます。
PL / SQLバージョンは、BULK COLLECT
を置き換えることで改善できます。 with cast(collect(test_o(MOD(a, 10), '' || MOD(a, 12))) as test_t) INTO t
。ただし、それでも一時テーブルバージョンよりも大幅に低速です。
最適化された読み取り
小さな一時テーブルからの読み取りでは、メモリ内にあるバッファキャッシュのみが使用されます。クエリ部分のみを何度も実行し、consistent gets from cache
(メモリ)physical reads cache
中に増加します (ディスク)同じままです。
select name, value
from v$sysstat
where name in ('db block gets from cache', 'consistent gets from cache',
'physical reads cache');
最適化された書き込み
特に一時テーブルがON COMMIT DELETE ROWS
であるため、物理的なI/Oがないことが理想的です。 。そして、Oracleの次のバージョンがそのようなメカニズムを導入するかもしれないように思えます。ただし、この場合はそれほど重要ではありません。ディスクI/Oによって速度が低下することはないようです。
ロードステップを複数回実行してから、select * from v$active_session_history order by sample_time desc;
を実行します。 。ほとんどのI/OはBACKGROUND
です 、これは何も待っていないことを意味します。一時テーブルの内部ロジックは、通常のDMLメカニズムの単なるコピーであると思います。一般に、新しいテーブルデータは コミットされている場合は、ディスクに書き込む必要があります。オラクルは、たとえばログバッファからディスクにデータを移動することによって作業を開始する場合がありますが、実際のCOMMIT
が存在するまで急ぐことはありません。 。
PL / SQLの時間はどこに行きますか?
私は見当もつかない。複数のコンテキストスイッチがありますか、それともSQLエンジンとPL / SQLエンジンの間に単一の変換がありますか?私の知る限り、利用可能なメトリックのいずれも時間を示していません SQLとPL/SQLの切り替えに費やしました。
PL/SQLコードが遅い理由を正確に知ることはできないかもしれません。あまり気にしません。一般的な答えは、データベース作業の大部分はとにかくSQLで行わなければならないということです。 Oracleが、アドオン言語であるPL / SQLよりも、データベースのコアであるSQLの最適化に多くの時間を費やした場合は非常に理にかなっています。
追記
パフォーマンステストでは、connect by
を削除すると便利な場合があります 別のステップへのロジック。このSQLはデータをロードするための優れたトリックですが、非常に遅く、リソースを大量に消費する可能性があります。そのトリックでサンプルテーブルを一度ロードしてから、そのテーブルから挿入する方が現実的です。
新しいOracle12c機能である一時的な取り消しと新しい18c機能であるプライベート一時テーブルを使用してみました。どちらも通常の一時テーブルよりもパフォーマンスが向上しませんでした。
私はそれには賭けませんが、データが大きくなるにつれて結果が完全に変化する方法を見ることができます。ログバッファとバッファキャッシュは非常に大きくなるだけです。そして最終的には、そのバックグラウンドI / Oが追加されて一部のプロセスを圧倒し、BACKGROUND
を変える可能性があります。 FOREGROUND
で待ちます 待つ。一方、PL / SQLソリューション用のPGAメモリはそれほど多くないため、問題が発生します。
最後に、これは「インメモリデータベース」に対する私の懐疑論を部分的に裏付けています。キャッシングは目新しいことではなく、データベースは何十年もの間それを行ってきました。