web-dev-qa-db-ja.com

Oracleオプティマイザーは同じSELECTで複数のヒントを使用しますか?

クエリのパフォーマンスを最適化しようとしているので、オプティマイザヒントを使用する必要がありました。しかし、オプティマイザが一度に複数のヒントを使用するかどうかは知りませんでした。

例えば.

SELECT /*+ INDEX(i dcf_vol_prospect_ids_idx)*/
       /*+ LEADING(i vol) */ 
       /*+ ALL_ROWS */ 
       i.id_number,
       ...
  FROM i_table i
  JOIN vol_table vol on vol.id_number = i.id_number
  JOIN to_a_bunch_of_other_tables...
 WHERE i.solicitor_id = '123'
   AND vol.solicitable_ind = 1;

説明プランは同じコストを示していますが、それは単なる見積もりです。

すべてのテーブルとインデックスの統計が計算されていると想定してください。参考までに、インデックスdcf_vol_prospect_ids_idxはi.solicitor_id列にあります。

おかげで、

シチュー

19
Stew S

素晴らしいOracleドキュメント( http://download.Oracle.com/docs/cd/B19306_01/server.102/b14211/hintsref。)のこの例に示すように、すべてのヒントを単一のコメントブロックで指定してみてください。 htm )。

16.2.1ヒントの完全なセットの指定

ヒントを使用する場合、最適な実行プランを確保するために、ヒントの完全なセットを指定する必要がある場合があります。たとえば、多くのテーブル結合で構成される非常に複雑なクエリがあり、特定のテーブルにINDEXヒントのみを指定した場合、オプティマイザは、使用される残りのアクセスパスと対応するアクセスパスを決定する必要があります。結合メソッド。したがって、INDEXヒントを指定したとしても、オプティマイザが選択した結合方法とアクセスパスが原因で要求されたインデックスを使用できないとオプティマイザが判断したため、オプティマイザが必ずしもそのヒントを使用するとは限りません。

例16-1では、LEADINGヒントは、使用される正確な結合順序を指定しています。異なるテーブルで使用される結合方法も指定されます。

例16-1ヒントの完全なセットの指定

SELECT /*+ LEADING(e2 e1) USE_NL(e1) INDEX(e1 emp_emp_id_pk)
           USE_MERGE(j) FULL(j) */
    e1.first_name, e1.last_name, j.job_id, sum(e2.salary) total_sal  
FROM employees e1, employees e2, job_history j
WHERE e1.employee_id = e2.manager_id
  AND e1.employee_id = j.employee_id
  AND e1.hire_date = j.start_date
GROUP BY e1.first_name, e1.last_name, j.job_id   ORDER BY total_sal;
22
Dave Costa

実際、コストベースのOracle Fundamentalsの作者であるJonathan Lewisの推奨は、CBOが正しい計画を見つけることができない場合、CBOの仕事を引き継ぎ、ヒントを「レイヤーイン」する必要があります。クエリのテーブルごとに2つのヒント。

その理由は、1つのヒントが、CBOの助けを借りないよりもさらに悪い、場合によってはさらに悪い計画につながる可能性があるためです。 CBOが間違っている場合は、正しい方向へのナッジだけでなく、計画全体を与える必要があります。

2
Mark Brady

Oracle 19cが導入されました ヒント使用状況レポート機能

EXPLAIN PLAN FOR
SELECT /*+ INDEX(i dcf_vol_prospect_ids_idx)*/
       /*+ LEADING(i vol) */ 
       /*+ ALL_ROWS */ 
       i.id_number,
       ...
  FROM i_table i
  JOIN vol_table vol on vol.id_number = i.id_number
  JOIN to_a_bunch_of_other_tables...
 WHERE i.solicitor_id = '123'
   AND vol.solicitable_ind = 1;

SELECT * FROM table(DBMS_XPLAN.DISPLAY(FORMAT=>'BASIC +HINT_REPORT'));
                                                     --============

別のセクションHint Report

Hint Report (identified by operation id / Query Block Name / Object Alias):
Total hints for statement: ...
---------------------------------------------------
...
2
Lukasz Szozda