簡単な些細なクエリを紹介しましょう:
SET echo OFF SET linesize 192 SET pagesize 0 SET TRIM ON SET trims ON SET feedback OFF SET heading OFF SET term OFF SET TIME ON SET timing ON SET autot ON stat spool s.txt SELECT clnt_clnt_id, name, start_date, end_date FROM client_histories; spool OFF exit
すべてがシンプルなようです:
- テーブルから選択が行われます
- 結果はファイルに駆動されます
- 結果は端末に表示されません
- リクエストの最後に、時間と統計が表示されます
次に、統計を見てみましょう。
.: 00:00:17.97 ---------------------------------------------------------- 0 recursive calls 0 db block gets 6515 consistent gets 0 physical reads 0 redo size 14182576 bytes sent via SQL*Net to client 242558 bytes received via SQL*Net from client 22012 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 330154 rows processed
ここで、データを合理化する必要があると想像してください。 質問-時間とともにどうなりますか? 最初の意見は、ソートには時間がかかり、結果は後から来るということです。 よくやった:
SET echo OFF SET linesize 192 SET pagesize 0 SET TRIM ON SET trims ON SET feedback OFF SET heading OFF SET term OFF SET time ON SET timing ON SET autot ON stat spool s1.txt SELECT clnt_clnt_id , name , start_date , end_date FROM client_histories ORDER BY 1, 2; spool OFF exit
次に、統計を見てみましょう。
.: 00:00:16.92 ---------------------------------------------------------- 0 recursive calls 0 db block gets 6115 consistent gets 0 physical reads 0 redo size 13166047 bytes sent via SQL*Net to client 242558 bytes received via SQL*Net from client 22012 SQL*Net roundtrips to/from client 1 sorts (memory) 0 sorts (disk) 330154 rows processed
order byを使用した場合、結果がより速く得られることがわかりました。 統計では、操作に費やされる時間とSQL * Netを介して送信される情報量の2つの違いのみがあります。
結論の1つは、既存のチャネルで992 kbのデータを送信するよりも、ソート操作が33,000行速いことです。
しかし、違いはどこから来たのですか?..
そして、事はsql * netを介して送信されたデータはバッファによって圧縮され、圧縮されるということです。 これは、TNS SQL * Net記述のSDUサイズと、デフォルトで15であるARRAYSIZEパラメーターを使用してSQL * Plusで構成されたバッファーのサイズの影響を受けます。データがソートされている場合、バッファーのデータは同じになり、圧縮率は高くなります。 T.O. SQL * Netを介して転送されるデータは少なくなります。
実験してみましょう。つまり、2番目のスクリプトに小さな変更を加えます。
SET autot ON stat SET arraysize 5000 spool s1.txt
これで、バッファーのサイズを5000(これが最大値)に増やし、ソートを使用してリクエストを実行しました。 結果を見てみましょう:
.: 00:00:06.47 ---------------------------------------------------------- 0 recursive calls 0 db block gets 6115 consistent gets 0 physical reads 0 redo size 11278863 bytes sent via SQL*Net to client 1174 bytes received via SQL*Net from client 68 SQL*Net roundtrips to/from client 1 sorts (memory) 0 sorts (disk) 330154 rows processed
- クライアントに送信される情報量をさらに1.8Mb削減しました
- クライアントから送信される情報量を200倍(235kb)削減しました
- ラウンドトリップ(クライアントとSQL * Netサーバー間のクエリ)の回数を300倍(22012から68)削減しました。
合計:バッファの増加により、データ転送中のラウンドトリップの回数が減ります。これは、ほとんどの場合、大きなリクエストに対してプラスの効果をもたらします。 しかし、興味深いことに、低速の通信チャネル(たとえば、1 m /ビット以下)では、通常のデータの並べ替えでさえ、リクエスト配信の結果にプラスの影響を与える可能性があります。
はい、圧縮の観点から。 次のようにデータを準備します。
CREATE TABLE tbl0 AS SELECT object_name, object_id, min(object_id) over (partition BY object_name) AS min_object_id FROM dba_objects; CREATE TABLE tbl1 AS SELECT DISTINCT object_name, object_id FROM tbl0 WHERE object_id = min_object_id; CREATE TABLE tbl2 AS SELECT object_name FROM tbl1 WHERE rownum < 1; BEGIN FOR i IN 1..20 LOOP INSERT INTO tbl2 SELECT object_name FROM tbl1 ORDER BY reverse(object_id||object_name); END LOOP; COMMIT; END;
ここで、ARRAYSIZE 5000の統計とクエリを比較します。
SELECT object_name FROM tbl2; SELECT object_name FROM tbl2 ORDER BY 1;
次の統計を取得します。
---------------------------------------------------------- 0 recursive calls 0 db block gets 4992 consistent gets 0 physical reads 0 redo size 34152895 bytes sent via SQL*Net to client 3088 bytes received via SQL*Net from client 250 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1242280 rows processed ---------------------------------------------------------- 167 recursive calls 16 db block gets 5211 consistent gets 16377 physical reads 0 redo size 7629058 bytes sent via SQL*Net to client 3088 bytes received via SQL*Net from client 250 SQL*Net roundtrips to/from client 21 sorts (memory) 4 sorts (disk) 1242280 rows processed
ご覧のように、ARRAYSIZE 5000を使用すると、同じ数の往復で120万行すべてがポンピングされます。 SQLの影響*リクエスト/レスポンスに対するネット遅延はほぼ同じですが、ソートされたデータの情報量は、ソートされていないデータの32.5 mbに対して7.3 mbです。 T.O. 繰り返しデータの予備ソートでは、ネットワーク上のトラフィック量を4.5倍削減しました。これは、低速の通信チャネルでは非常に重要です。