Oracle优化器是否会在同一个SELECT中使用多个提示?

时间:2009-01-07 20:38:41

标签: sql oracle optimization hints

我正在尝试优化查询性能,不得不求助于使用优化器提示。但我从来没有学过优化器是否会一次使用多个提示。

e.g。

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列上。

谢谢,

3 个答案:

答案 0 :(得分:22)

尝试在单个注释块中指定所有提示,如本例中的精彩Oracle文档(http://download.oracle.com/docs/cd/B19306_01/server.102/b14211/hintsref.htm)所示。

  

16.2.1指定一整套提示

     

使用提示时,在某些情况下,您   可能需要指定一整套   提示以确保最佳   执行计划。例如,如果你   有一个非常复杂的查询,其中   由许多表连接组成,如果   您只为a指定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;

答案 1 :(得分:2)

事实上,基于成本的Oracle基础知识作者Jonathan Lewis的建议是,如果CBO未能找到正确的计划,您需要接管CBO的工作并“提入”提示 - 查询中每个表平均有两个提示。

原因在于,一条暗示可能会导致另一个糟糕甚至可能更糟糕的计划,而不是CBO可以独立完成的计划。如果CBO错了,你需要给它整个计划,而不仅仅是朝着正确的方向推进。

答案 2 :(得分:1)

Oracle 19c引入了here

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: ...
---------------------------------------------------
...