0

私のプロジェクトの1つでは、dblinkを使用してViewで直接クエリを実行していますが、パフォーマンスチェックの後、コストがかかることがわかりました(ネストされたループが多く、CPUの使用率が高い)。

これで、1 つの解決策が見つかりました。つまり、関数を使用してビューでこれらのクエリを起動します。それは正しい解決策ですか、それともこの操作を実行するためのより良い方法はありますか?

サンプル クエリとパフォーマンス レポート:

  1. 関数を使用しない場合:

クエリ:

SELECT t1.,
       t2.
FROM   table1 t1
       join table2 t2
         ON t1.id = t2.id
WHERE  t1.bookingId = '0250014547' 

パフォーマンスレポート:

SQL> explain plan for SELECT t1., t2. FROM table1 t1 JOIN table2 t2 ON t1.id = t2.id WHERE t1.bookingId = '0250014547';

SQL> select * from table(dbms_xplan.display);

-------------------------------------------------------------------------------------------
| Id  | Operation                        | Name                     | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                 |                          |     1 |   331 |     6   (0)| 00:00:01 |
|   1 |  NESTED LOOPS                    |                          |     1 |   331 |     6   (0)| 00:00:01 |
|   2 |   NESTED LOOPS                   |                          |     1 |   299 |     5   (0)| 00:00:01 |
|   3 |    NESTED LOOPS                  |                          |     1 |   210 |     4   (0)| 00:00:01 |
|   4 |     NESTED LOOPS                 |                          |     1 |   185 |     3   (0)| 00:00:01 |
|   5 |      NESTED LOOPS                |                          |     1 |   156 |     2   (0)| 00:00:01 |
|*  6 |       TABLE ACCESS BY INDEX ROWID| GENERAL_ACCT_MAST_TABLE  |     1 |    66 |     1   (0)| 00:00:01 |
|*  7 |        INDEX UNIQUE SCAN         | IDX_GAM_FORACID          |     1 |       |     1   (0)| 00:00:01 |
|   8 |       TABLE ACCESS BY INDEX ROWID| SERVICE_OUTLET_TABLE     |  1694 |   148K|     1   (0)| 00:00:01 |
|*  9 |        INDEX UNIQUE SCAN         | IDX_SERVICE_OUTLET_TABLE |     1 |       |     1   (0)| 00:00:01 |
|  10 |      TABLE ACCESS BY INDEX ROWID | GEN_SCHM_PARM_TABLE      |   356 | 10324 |     1   (0)| 00:00:01 |
|* 11 |       INDEX UNIQUE SCAN          | IDX_GEN_SCHM_PARM_TABLE  |     1 |       |     1   (0)| 00:00:01 |
|* 12 |     TABLE ACCESS BY INDEX ROWID  | ACCT_STATEMENT_TABLE     |    12M|   309M|     1   (0)| 00:00:01 |
|* 13 |      INDEX UNIQUE SCAN           | IDX_ACCT_STATEMENT_TABLE |     1 |       |     1   (0)| 00:00:01 |
|  14 |    TABLE ACCESS BY INDEX ROWID   | CUST_MAST_GEN_TABLE      |    24M|  2119M|     1   (0)| 00:00:01 |
|* 15 |     INDEX UNIQUE SCAN            | IDX_CUST_MAST_GEN_TABLE  |     1 |       |     1   (0)| 00:00:01 |
|  16 |   TABLE ACCESS BY INDEX ROWID    | BRANCH_BIC_TABLE         | 65258 |  2039K|     1   (0)| 00:00:01 |
|* 17 |    INDEX UNIQUE SCAN             | IDX_BRANCH_BIC_TABLE     |     1 |       |     1   (0)| 00:00:01 |
-------------------------------------------------------------------------------------------
  1. 使用機能:

クエリ:

SELECT Funquery1('0250014547')
FROM   dual; 

パフォーマンスレポート:

SQL> explain plan for select gtt('0252050014577') from dual;

SQL> select * from table(dbms_xplan.display);

-----------------------------------------------------------------
| Id  | Operation        | Name | Rows  | Cost (%CPU)| Time     |
-----------------------------------------------------------------
|   0 | SELECT STATEMENT |      |     1 |     2   (0)| 00:00:01 |
|   1 |  FAST DUAL       |      |     1 |     2   (0)| 00:00:01 |
-----------------------------------------------------------------
4

2 に答える 2

2

2 番目のクエリは実際に高速に実行されますか?

一般に、SQL オプティマイザーは、関数内で何が行われているかを認識しておらず、関数内で何が行われているかはクエリ プランの一部ではありません。つまり、関数内にかなりの複雑さを隠して、クエリ プランをより効率的に見せることができます。ただし、これは、クエリが実際に高速に実行され、CPU の使用量が少なくなり、I/O 操作が少なくなることを意味するわけではありません。関数内にまったく同じロジックを配置している場合、関数が実行するクエリは元のクエリとまったく同じ計画を持っています。PL/SQL から SQL へのコンテキスト シフトがいくつか余分に発生する (わずかな) オーバーヘッドを除けば、同じパフォーマンスが得られます。

テーブルの統計は正確ですか? クエリ プランのカーディナリティの見積もりは現実にかなり近いですか? t1.bookingId = '0250014547'述語はどの程度選択的ですか? bookingIDの主キーt1は?

質問のテキストはデータベース リンクについて述べていますが、投稿したクエリもクエリ プランもリモート データベース内のオブジェクトを参照していないようです。質問のテキストはビューについて語っていますが、投稿したクエリはビューを参照していません。投稿したクエリは 2 つのテーブルを結合しており、クエリ プランは 7 を結合しています。一般に、これらの種類の不一致により、提案を提供することがより複雑になります。

于 2012-06-20T13:14:38.623 に答える
0

ジャスティン (+1) はまさにその通りです。EXPLAIN PLAN は関数の呼び出しを示しており、関数内で起こっていることは何も示していません。

SQLPlus では、

set autotrace on

これにより、EXPLAIN PLAN 出力には表示されない再帰 SQL を含む、ステートメント実行の実際の統計が得られます。

より高度なチューニングを行うには、Oracle トレース イベント 10046 を使用できます。ただし、目的には SQLPlus の「自動トレース」で十分な場合があります。

(DB_LINK を介して) リモート データベースのテーブル/ビューを含むステートメントをチューニングすることは、送信するステートメントとリモート データベースに送信されるステートメントの両方をチューニングする必要があるため、面倒な場合があります。

于 2012-06-21T19:25:44.943 に答える