4

私はオラクルの説明計画を理解しようとしていましたが、説明計画を作成する際にオラクルが考慮する条件を知りたいと思っていました。

Oracle 11gに存在するHRスキーマで単純なクエリをテストしていました

select * from countries 
where region_id in (select region_id from regions where region_name = 'Europe');

次のクエリを実行したとき:

explain plan for 
select * from countries 
where region_id in (select region_id from regions where region_name = 'Europe');

SELECT * FROM table(dbms_xplan.display(null,null,'basic'));

説明テーブルに次の出力が表示されました。

--------------------------------------------------------
| Id  | Operation                    | Name            |
--------------------------------------------------------
|   0 | SELECT STATEMENT             |                 |
|   1 |  NESTED LOOPS                |                 |
|   2 |   INDEX FULL SCAN            | COUNTRY_C_ID_PK |
|   3 |   TABLE ACCESS BY INDEX ROWID| REGIONS         |
|   4 |    INDEX UNIQUE SCAN         | REG_ID_PK       |
--------------------------------------------------------

ここで、外側のクエリが最初に実行されたことを確認しました。つまり、行 3 で示されているように、countries テーブルが最初に実行されました。

ここで、regions テーブルの region_name にインデックスを追加し、説明計画を再度実行して、次の出力を得ました。

--------------------------------------------------------------
| Id  | Operation                    | Name                  |
--------------------------------------------------------------
|   0 | SELECT STATEMENT             |                       |
|   1 |  NESTED LOOPS                |                       |
|   2 |   TABLE ACCESS BY INDEX ROWID| REGIONS               |
|   3 |    INDEX RANGE SCAN          | REGIONNAME_REGIONS_IX |
|   4 |   INDEX UNIQUE SCAN          | COUNTRY_C_ID_PK       |
|   5 |    INDEX RANGE SCAN          | COUNTRIES_REGIONID_IX |
--------------------------------------------------------------

今私の質問は:

  1. インデックスが存在するかどうかに関係なく、最初に内部クエリを実行するべきではありませんか
  2. インデックスを追加すると実行計画が変更される場合、それを変更できる他の機能は何ですか?
  3. 一般的に、実行プロセスはどのようなものですか? (最初に発生する結合を最初に実行し、次にクエリ内の次の結合に進みます) ?

よろしくお願いします。

-ヴァルン

4

3 に答える 3

2

説明計画は、Cost Based Optimizer (CBO) に大きく依存しています。クエリを実行しているテーブルの統計を収集することで、このプロセスを支援できます。インデックスが計画を変更する理由については、CBO に以前は提供されていなかった重要な情報を提供したためです。これは、私があなたにこの質問をするのと同じです:

索引なし:
「通りはどこですか?」

索引付き:
「青い家が建っている通りはどこですか?」

2 番目の質問は、より詳細なコンテキストを提供するため、より迅速に推測できます。また、道路などすべてを列挙する必要はありません。

クエリにヒントを指定できます。つまり、次のようになります。

select /*+ parallel */ * from table
このクエリを並行して実行する ためのヒントを提供します。

3番目の質問については、オラクルのプロセスの一部であり、世界が利用できるように文書化されていないと思います。

最初の質問では、必ずしもそうではありませんが、すべてコストベースです。

于 2013-03-22T17:15:01.907 に答える
1

コストベースのオプティマイザーは、クエリの変換を含むいくつかの段階を経ます。あなたのクエリは、ほぼ確実にオプティマイザによって次のように書き換えられています。

select countries.* from countries join regions on (countries.region_id = regions.region_id) where regions.region_name = 'Europe';

そのため、元のクエリで表されている内部クエリと外部クエリの概念は、変換後は適用されない場合があります。ちなみに、これが EXISTS () と IN () に関する引数がしばしば意味のない理由です。両方の場合のクエリはしばしば結合として書き直すことができます。

オプティマイザーが使用する情報 (バージョンに依存) には次のものがあります。

  1. テーブルの統計
  2. 表の列に関する統計
  3. テーブルの列値のヒストグラム
  4. インデックスの存在
  5. インデックスのサイズとタイプ、およびインデックスの統計 -- 特にクラスタリング係数
  6. 制約の存在 -- not null および check 制約を含む。
  7. 1 秒あたりのシングルおよびマルチブロック読み取りと CPU オペレーションの推定コスト。
  8. パーティショニング
  9. マテリアライズド ビューやクエリ書き換え宣言の存在と状態。
  10. 以前のバージョンのクエリのパフォーマンス。

要するに、オプティマイザが何をしても驚かないでください。とても洗練されたキットです。

于 2013-03-23T10:02:15.207 に答える
1

11g の実行計画の出力で何かが変更されたかどうかはわかりませんが、正しいクエリを表示していると確信していますか? select *テーブルcountriesからすべての列 ( ) を選択していますが、Explain Plan にはテーブルへのアクセスが表示されませんか? またはCOUNTRY_C_ID_PK、すべての列が含まれますか?

次の計画を期待します(インデックスなし):

SELECT
  NESTED LOOP
    FULL TABLE SCAN (regions)
    TABLE ACCESS BY INDEX ROWID (countries)
      INDEX RANGE SCAN (COUNTRIES_REGIONID_IX)

インデックスを配置すると、次のようになります。

SELECT
  NESTED LOOP
    TABLE ACCESS BY INDEX ROWID (regions)
      INDEX RANGE SCAN (REGIONNAME_REGIONS_IX)
    TABLE ACCESS BY INDEX ROWID (countries)
      INDEX RANGE SCAN (COUNTRIES_REGIONID_IX)

ご質問について:

  1. Oracle は、使用可能な統計に応じて、適切と思われる内部クエリまたは外部クエリからクエリを実行する場合があります。
  2. 実行計画に影響を与えるものはたくさんあります...
  3. Oracle では、一度に 2 つのテーブル (または行ソース) しか結合できません。結合の結果は、次のテーブルに結合できる行ソースでもあります
于 2013-03-22T22:46:06.113 に答える