Karl about the Oracle Database

Some experiences out of my daily oracle practice

No more Hints in Oracle 10G?

Posted by carl.reitschuster on April 27th, 2006

Hi reader,

With Oracle 10G specially with 10.2 you often hear :

! DO NOT USE HINTS ANY MORE! THEY ARE NOT NEEDED ANY MORE ! 

So thinking of the possibility to use a hint for a statement gives you a bad feeling doing something wrong. It’s clear to use hints only if there is no way to bring the optimizer to the desired execution plan or if the plan stability is most important even independent from gathered table/index stats.

Yesterday i navigated with the Db Console thru some SQL-Statements run in the past. Accidentally i found an interesting statement:

As you see this SELECT statement uses the NO_MERGE and ORDERED hint. It was executed via Db Console well known as an Oracle product ;-). And even the RULE hint seems (it’s not) to be out in Oracle 10.2, with these hints you dictate the query optimizer what plan to generate.

The SQL again - better formatted for discussion:

SELECT Task_List.Task_Id
 
FROM (SELECT /*+ NO_MERGE(T) ORDERED */

         t.Task_Id
         
FROM (SELECT *
                 
FROM Dba_Advisor_Tasks
                
ORDER BY Task_Id DESC) t,

               Dba_Advisor_Parameters_Proj P1
,
               Dba_Advisor_Parameters_Proj P2
        
WHERE t.Advisor_Name = ‘ADDM’
          
AND t.Status = ‘COMPLETED’
          
AND t.Execution_Start >= (SYSDATE - 1)
          
AND t.How_Created = ‘AUTO’
          
AND t.Task_Id = P1.Task_Id
           
AND P1.Parameter_Name = ‘INSTANCE’

          
AND P1.Parameter_Value = Sys_Context(‘USERENV’,
                                               
‘INSTANCE’)
          
AND t.Task_Id = P2.Task_Id
          
AND P2.Parameter_Name = ‘DB_ID’

          
AND P2.Parameter_Value = To_Char(:B1)
        
ORDER BY t.Task_Id DESC) Task_List
 
WHERE Rownum = 1

The NO_MERGE hint dictates the optimizer not to merge the sub query


SELECT *
 
FROM Dba_Advisor_Tasks
 
ORDER BY Task_Id DESC

into the rest of the statement, some kind of rewriting the query for performance reasons. This means the sub query is executed as it is written.

The ORDERED hint dictates the optimizer the join order of the tables.  The join orders of the tables then is depending on the order in the FROM table list . So the execution plan accesses T(Dba_Advisor_Tasks), P1(Dba_Advisor_Parameters_Proj), P2(Dba_Advisor_Parameters_Proj);

Let’s take a look at the EXPLAIN PLAN :

SQL> explain plan for
  2  SELECT Task_List.Task_Id
  3    FROM (SELECT /*+ NO_MERGE(T) ORDERED */
  4           t.Task_Id
  5            FROM (SELECT *
  6                    FROM Dba_Advisor_Tasks
  7                   ORDER BY Task_Id DESC) t,
  8                 Dba_Advisor_Parameters_Proj P1,
  9                 Dba_Advisor_Parameters_Proj P2
 10           WHERE t.Advisor_Name = ‘ADDM’
 11             AND t.Status = ‘COMPLETED’
 12             AND t.Execution_Start >= (SYSDATE - 1)
 13             AND t.How_Created = ‘AUTO’
 14             AND t.Task_Id = P1.Task_Id
 15             AND P1.Parameter_Name = ‘INSTANCE’
 16             AND P1.Parameter_Value = Sys_Context(’USERENV’,
 17                                                  ‘INSTANCE’)
 18             AND t.Task_Id = P2.Task_Id
 19             AND P2.Parameter_Name = ‘DB_ID’
 20             AND P2.Parameter_Value = To_Char(:B1)
 21           ORDER BY t.Task_Id DESC) Task_List
 22   WHERE Rownum = 1
 23  ;

EXPLAIN PLAN ausgef³hrt.

SQL> SELECT * FROM table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
————————————————————————————————————
Plan hash value: 2107564592

———————————————————————————————————–
| Id  | Operation                        | Name                   | Rows  | Bytes | Cost (%CPU)| Time     |
———————————————————————————————————–
|   0 | SELECT STATEMENT                 |                        |     1 |    13 |    19   (6)| 00:00:01 |
|*  1 |  COUNT STOPKEY                   |                        |       |       |            |       |
|   2 |   VIEW                           |                        |     1 |    13 |    19   (6)| 00:00:01 |
|*  3 |    SORT ORDER BY STOPKEY         |                        |     1 |   102 |    19   (6)| 00:00:01 |
|   4 |     NESTED LOOPS                 |                        |     1 |   102 |    18   (0)| 00:00:01 |
|   5 |      NESTED LOOPS                |                        |     1 |    78 |    17   (0)| 00:00:01 |

PLAN_TABLE_OUTPUT
————————————————————————————————————
|   6 |       VIEW                       |                        |     1 |    54 |    16   (0)| 00:00:01 |
|*  7 |        TABLE ACCESS FULL         | WRI$_ADV_TASKS         |     1 |    29 |    16   (0)| 00:00:01 |
|*  8 |       TABLE ACCESS BY INDEX ROWID| WRI$_ADV_PARAMETERS    |     1 |    24 |     1   (0)| 00:00:01 |
|*  9 |        INDEX UNIQUE SCAN         | WRI$_ADV_PARAMETERS_PK |     1 |       |     1   (0)| 00:00:01 |
|* 10 |      TABLE ACCESS BY INDEX ROWID | WRI$_ADV_PARAMETERS    |     1 |    24 |     1   (0)| 00:00:01 |
|* 11 |       INDEX UNIQUE SCAN          | WRI$_ADV_PARAMETERS_PK |     1 |       |     1   (0)| 00:00:01 |
———————————————————————————————————–

The Explain Plan confirms the effectiveness of the described hints. In the example you see another interesting point. The plan starts with TABLE ACCESS FULL OPERATION on WRI$_ADV_TASKS. As next operation after a full table scan i would expect a HASH JOIN Operation. But the Optimizer uses a NESTED LOOPS instead. Why?

It’s all about expected CARDINALITY[1]! Because only 1 Row is expected via TABLE ACCESS FULL Operation a NESTED LOOPS Join Operation is the correct answer.

I removed the Predicate[2] Information section for better overview. How would be the Explain Plan without Hints?

———————————————————————————————————–
| Id  | Operation                        | Name                   | Rows  | Bytes | Cost (%CPU)| Time     |
———————————————————————————————————–
|   0 | SELECT STATEMENT                 |                        |     1 |    13 |    19   (6)| 00:00:01 |
|*  1 |  COUNT STOPKEY                   |                        |       |       |            |       |
|   2 |   VIEW                           |                        |     1 |    13 |    19   (6)| 00:00:01 |
|*  3 |    SORT ORDER BY STOPKEY         |                        |     1 |   102 |    19   (6)| 00:00:01 |
|   4 |     NESTED LOOPS                 |                        |     1 |   102 |    18   (0)| 00:00:01 |
|   5 |      NESTED LOOPS                |                        |     1 |    78 |    17   (0)| 00:00:01 |

PLAN_TABLE_OUTPUT
———————————————————————————————————–
|   6 |       VIEW                       |                        |     1 |    54 |    16   (0)| 00:00:01 |
|*  7 |        TABLE ACCESS FULL         | WRI$_ADV_TASKS         |     1 |    29 |    16   (0)| 00:00:01 |
|*  8 |       TABLE ACCESS BY INDEX ROWID| WRI$_ADV_PARAMETERS    |     1 |    24 |     1   (0)| 00:00:01 |
|*  9 |        INDEX UNIQUE SCAN         | WRI$_ADV_PARAMETERS_PK |     1 |       |     1   (0)| 00:00:01 |
|* 10 |      TABLE ACCESS BY INDEX ROWID | WRI$_ADV_PARAMETERS    |     1 |    24 |     1   (0)| 00:00:01 |
|* 11 |       INDEX UNIQUE SCAN          | WRI$_ADV_PARAMETERS_PK |     1 |       |     1   (0)| 00:00:01 |
———————————————————————————————————–

This is no pasting error - it was the same execution plan (i flushed the shared pool before)! But nevertheless without hint depending on sampled stats the execution plan could change.

Conclusion

With Oracle 10G the technique using hints is still a very important tool for statement tuning. In project field sometimes a hint  is used to fast. There are other possibilities to influence an execution plan.

  • are indexes missing?
  • change the physical structure using IOT’s , partitions, clusters
  • Query rewrite using materialized views
  • is the kind of data model weak designed
  • change your gather statistics parameter/method
  • use of sql profiles (Oracle 10.x)
  • patching object/system statistics

CBO still is in need of manual assistance because it’s estimations are based on an ideal model which often does not fit the reality.

HTH Karl


[1] Predicates are comparison expressions in the where clause of an SQL Statement.
[2] Cardinality here is the number of expected rows of an operation of an explain plan.

2 Responses to “No more Hints in Oracle 10G?”

  1. dave Says:

    You really write some rubbish sometime, try researching your facts first

  2. carl.reitschuster Says:

    Hi Dave
    could you please specify more what you mean?
    I would appreciate it.

    Greetings
    Karl

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>