Skip to Main Content

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Girish.

Asked: January 07, 2014 - 9:59 am UTC

Last updated: January 10, 2014 - 5:51 pm UTC

Version: Oracle 11g

Viewed 1000+ times

You Asked

Hi Tom,

I have a query with hint which is used in Pro*C like

select /*+ index(emp,pk_emp_id) */ from emp where emp_id = l_empid;

When we run this Pro*C job and generate a tkprof file this query appears as

select /*+ index(emp,pk_emp_id) +*/ from emp where emp_id = :B1;

If you see syntax of hint it is not correct and but still gets applied to the query.And to test I tried it on SQL Developer and generated explain plan to see whether index will be used.Yes it is used.

How it Oracle use this hint with incorrect syntax ?
Could you please explain ?

Thanks,
Girish

and Tom said...

what if I ran a query:

select /*+ Hello World!!!!! */ * from emp where emp_id = :b1;


and it used the index... does that imply/infer that the "hint" Hello World!!!!! was the reason the hint was used?


if you just run:

select * from emp where emp_id = :b1;

without a hint, I would expect the index to be used as well (emp_id would be a primary key, it'll get 1 row, typically to get 1 row from a table by a primary key - the optimizer would tend to use the primary key index!)


But in this case, you might be surprised. We can use a 10053 optimizer dump to see what the optimizer is actually dealing with. For example:


ops$tkyte%ORA11GR2> create table emp as select * from scott.emp;

Table created.

ops$tkyte%ORA11GR2> alter table emp add constraint emp_pk primary key(empno);

Table altered.

ops$tkyte%ORA11GR2> 
ops$tkyte%ORA11GR2> set autotrace traceonly explain
ops$tkyte%ORA11GR2> select * from emp where empno = 1234;

Execution Plan
----------------------------------------------------------
Plan hash value: 4024650034

--------------------------------------------------------------------------------------
| Id  | Operation                   | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |        |     1 |    87 |     1   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| EMP    |     1 |    87 |     1   (0)| 00:00:01 |
|*  2 |   INDEX UNIQUE SCAN         | EMP_PK |     1 |       |     0   (0)| 00:00:01 |
--------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("EMPNO"=1234)

ops$tkyte%ORA11GR2> set autotrace off
ops$tkyte%ORA11GR2> 
ops$tkyte%ORA11GR2> variable n number;
ops$tkyte%ORA11GR2> exec :n := 1234;

PL/SQL procedure successfully completed.

ops$tkyte%ORA11GR2> 
ops$tkyte%ORA11GR2> @10053
ops$tkyte%ORA11GR2> alter session set events '10053 trace name context forever, level 1';

Session altered.

ops$tkyte%ORA11GR2> select /*+ index(emp,emp_pk) */ * from emp where empno = :n;

no rows selected


so here we have an EMP table, primary key on EMPNO and "where empno = some_number" will tend to use the index regardless. We run the hinted query using what "appears" to be an invalid hint (has a comma, doesn't need a comma, but is actually allowed to use a comma) but if we review the trace file - we'll see:

Final query after transformations:******* UNPARSED QUERY IS *******
SELECT /*+ INDEX ("EMP" "EMP_PK") */ "EMP"."EMPNO" "EMPNO","EMP"."ENAME" "ENAME","EMP"."JOB" "JOB","EMP"."MGR" "MGR","EMP"."HIREDATE" "HIREDATE","EMP"."SAL" "SAL","EMP"."COMM" "COMM","EMP"."DEPTNO" "DEPTNO" FROM "OPS$TKYTE"."EMP" "EMP" WHERE "EMP"."EMPNO"=:B1
kkoqbc: optimizing query block SEL$1 (#0)



and further more we can see:

  atom_hint=(@=0x4b6fdc err=0 resol=1 used=1 token=83 org=1 lvl=3 txt=INDEX ("EMP" "EMP_PK") )


indicating the hint was used and was not in error...


the comma is allowed but not required:

http://docs.oracle.com/cd/E11882_01/server.112/e41084/sql_elements006.htm#SQLRF51102

<quote>
When tablespec is followed by indexspec in the specification of a hint, a comma separating the table name and index name is permitted but not required. Commas are also permitted, but not required, to separate multiple occurrences of indexspec.
</quote>


Rating

  (7 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Girish Jahagirdar, January 08, 2014 - 6:37 am UTC

so that means that like comma /*+ hint +*/ is also permitted but not required right ?
Tom Kyte
January 08, 2014 - 6:16 pm UTC

I don't know what you mean?

do you mean "can I put random words into the hint?" if so, this would be hinting the query to use parallel...

select /*+ parallel is bad for this query, do not use it!! */ count(*)
from t

Plan hash value: 3126468333

--------------------------------------------------------------------------------------------------------
| Id  | Operation              | Name     | Rows  | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |
--------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |          |       |  3770 (100)|          |        |      |            |

|   2 |   PX COORDINATOR       |          |       |            |          |        |      |            |
|   3 |    PX SEND QC (RANDOM) | :TQ10000 |     1 |            |          |  Q1,00 | P->S | QC (RAND)  |
|   4 |     SORT AGGREGATE     |          |     1 |            |          |  Q1,00 | PCWP |            |
|   5 |      PX BLOCK ITERATOR |          |    10M|  3770   (1)| 00:00:46 |  Q1,00 | PCWC |            |
|*  6 |       TABLE ACCESS FULL| T        |    10M|  3770   (1)| 00:00:46 |  Q1,00 | PCWP |            |
--------------------------------------------------------------------------------------------------------


Hint is supported

Pinson, January 08, 2014 - 9:34 am UTC

Hi, had the same issue, have opened an SR, Oracle Support confirms that the hint is followed and that Oracle dev will fix this in a future release.
Tom Kyte
January 08, 2014 - 6:18 pm UTC

fix what? nothing is "broken" here

the hint was valid - and even if it was not - the fact we used an index does not mean the hint was used...

I'm confused as to what is "broken" and due to be fixed?

Hints

A reader, January 09, 2014 - 1:38 am UTC


I guess people are getting confused or over thinking it. If a reserved word is used as a hint, as in the case of Tom's example where he used parallel, the hint is used.

The key being "+" w/o which it is just a comment. Had that been excluded it would have not taken affect.

I agree with Tom nothing is broken here. The DB is doing just what it is being asked to and not going out of its way to add "spice" to the queries ;o)

Hiont syntax

A reader, January 09, 2014 - 8:49 am UTC

Hi Tom, What is broken is the hint syntax. Should be /*+ */ and, instead, the precompiler sets a syntax /*+ +*/. This is what will be fixed: to set the correct syntax. However, no worry, today both syntaxes are accepted and the hint will be considered by the optimizer in the same way as for the correct syntax . This is the answer I got from Oracle support when I have submited the question. They have concluded "Knowledge content not created because the issue is still being worked by development under P3/P4 Bug 12732092 - PRO*C PRECOMPILER ADDS EXTRA CHARACTERS TO THE END OF A HINT and therefore at this time not resolved. Also no further ODM headings were used for the same reason." Can't give you the exact date when I have opened this SR, as this is not recorded in it, only an indication " 2 years +" is shown.

Regards

Tom Kyte
January 09, 2014 - 7:10 pm UTC

there is nothing wrong with

/*+ xxxxxx +*/

it is the same as /*+ xxxxxx */

or /*+ xxxxxxx abcdefg*/

the white space is not necessary. +*/ closes a comment as well as */, as well as helloworld*/ as well as *anything*.

to be a hint, it must start with /*+, it must end with */ (unless you are using the other style hint of course). and that is all.


there is no bug to fix. there is nothing wrong here. There is no "broken syntax"

ops$tkyte%ORA11GR2> set autotrace traceonly explain
ops$tkyte%ORA11GR2> select count(*) from t;

Execution Plan
----------------------------------------------------------
Plan hash value: 2966233522

-------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Cost (%CPU)| Time     |
-------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     1 |     3   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE    |      |     1 |            |          |
|   2 |   TABLE ACCESS FULL| T    |     1 |     3   (0)| 00:00:01 |
-------------------------------------------------------------------

Note
-----
   - dynamic sampling used for this statement (level=2)

ops$tkyte%ORA11GR2> select /*+ parallel +*/ count(*) from t;

Execution Plan
----------------------------------------------------------
Plan hash value: 3126468333

--------------------------------------------------------------------------------------------------------
| Id  | Operation              | Name     | Rows  | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |
--------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |          |     1 |     2   (0)| 00:00:01 |        |      |            |
|   1 |  SORT AGGREGATE        |          |     1 |            |          |        |      |            |
|   2 |   PX COORDINATOR       |          |       |            |          |        |      |            |
|   3 |    PX SEND QC (RANDOM) | :TQ10000 |     1 |            |          |  Q1,00 | P->S | QC (RAND)  |
|   4 |     SORT AGGREGATE     |          |     1 |            |          |  Q1,00 | PCWP |            |
|   5 |      PX BLOCK ITERATOR |          |     1 |     2   (0)| 00:00:01 |  Q1,00 | PCWC |            |
|   6 |       TABLE ACCESS FULL| T        |     1 |     2   (0)| 00:00:01 |  Q1,00 | PCWP |            |
--------------------------------------------------------------------------------------------------------

Note
-----
   - dynamic sampling used for this statement (level=2)
   - automatic DOP: skipped because of IO calibrate statistics are missing

ops$tkyte%ORA11GR2> select /*+ parallel helloworld*/ count(*) from t;

Execution Plan
----------------------------------------------------------
Plan hash value: 3126468333

--------------------------------------------------------------------------------------------------------
| Id  | Operation              | Name     | Rows  | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |
--------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |          |     1 |     2   (0)| 00:00:01 |        |      |            |
|   1 |  SORT AGGREGATE        |          |     1 |            |          |        |      |            |
|   2 |   PX COORDINATOR       |          |       |            |          |        |      |            |
|   3 |    PX SEND QC (RANDOM) | :TQ10000 |     1 |            |          |  Q1,00 | P->S | QC (RAND)  |
|   4 |     SORT AGGREGATE     |          |     1 |            |          |  Q1,00 | PCWP |            |
|   5 |      PX BLOCK ITERATOR |          |     1 |     2   (0)| 00:00:01 |  Q1,00 | PCWC |            |
|   6 |       TABLE ACCESS FULL| T        |     1 |     2   (0)| 00:00:01 |  Q1,00 | PCWP |            |
--------------------------------------------------------------------------------------------------------

Note
-----
   - dynamic sampling used for this statement (level=2)
   - automatic DOP: skipped because of IO calibrate statistics are missing

ops$tkyte%ORA11GR2> set autotrace off

Husqvik, January 09, 2014 - 7:34 pm UTC

Actually the hints work with line comments as well, for instance:

HUSQVIK@hq_pdb_tcp> select --+ cardinality(dual 100)
  2  * from dual;

D
-
X

1 row selected.

HUSQVIK@hq_pdb_tcp> select * from table(dbms_xplan.display_cursor(null, null, null));

PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------------
SQL_ID  2ky4jfpxm6rvx, child number 0
-------------------------------------
select --+ cardinality(dual 100) * from dual

Plan hash value: 272002086

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |       |       |     2 (100)|          |
|   1 |  TABLE ACCESS FULL| DUAL |   100 |   200 |     2   (0)| 00:00:01 |
--------------------------------------------------------------------------


13 rows selected.

HUSQVIK@hq_pdb_tcp>

Tom Kyte
January 09, 2014 - 7:37 pm UTC

that is why I wrote above "unless you are using the other style hint of course"...

yes, --+ works, and can end with anything, such as +-- if you wanted :)


And in further releases?

Pinson, January 10, 2014 - 8:03 am UTC

Hi Tom,

Thansk for your answer.

Oracle support says this is bug (that "other" syntax works and is set by the precompiler), you say that this is NOT a bug. How about future releases? What warranty we have that this "other" syntax wuill work in future releases? Documentation is contradicted by this "othe" syntax, documentation says that a hint should be labelled /*+ <hint> */ and not /*+ <hint> +*/. The day we go to a release in which the "other" syntax is not supported and we get problems, Oracle Support will tell us that a hint should be labelled according to the syntax shown in the documentation.
I think that Oracle dev would not have opened a BUG if they wouldn't have too, isn't it?

Thanks,

Pinson
Tom Kyte
January 10, 2014 - 5:49 pm UTC

look at the documentation for a comment.

a hint is hidden in a comment.

a comment that starts with /*+ or --+

The comment ends with */

no one gives a care about what appears in between the /*+ and the */

the optimizer reads it and looks for well formed hints and then uses them.

anything that isn't a well formed hint is ignored.

the "+" in +*/ is just a character, it could be a space for all we care - it doesn't matter.

There is no "syntax" issue here - the syntax of a hint is you start with /*+, it is followed then by a hint (and other junk, it is just a comment after all), and then ends with */


Don't get lost in the forest for the trees on this.


Bugs get opened all of the time, only to be closed as "not a bug". In fact most of the bugs in the bug database are probably not bugs at all.

In fact, in the referenced bug I see

"When we discussed this previously the filer confirmed that the additional
plus sign has no effect on functionality - this is purely cosmetic. "


and I see they changed the pro*c behavior six years ago (even though the referenced bug was filed just three years ago), just to close this out. The referenced bug has been closed for two years now.

But it wasn't a bug in any sense, it was an annoyance at best. it didn't change any of the functionality. It was purely 100% cosmetic.



if the syntax were ever to become "unsupported" - THAT would be a bug (the unsupporting of the +*/!! would be a bug)

To Pinson - Regarding documentation

Kim Berg Hansen, January 10, 2014 - 9:32 am UTC

Hi, Pinson

Syntax diagram documentation on hints:

http://docs.oracle.com/cd/E16655_01/server.121/e17209/sql_elements006.htm#SQLRF00219

The explanation of the syntax diagram states:

- The plus sign (+) causes Oracle to interpret the comment as a list of hints. The plus sign must follow immediately after the comment delimiter. No space is permitted.

- hint is one of the hints discussed in this section. The space between the plus sign and the hint is optional. If the comment contains multiple hints, then separate the hints by at least one space.

- string is other commenting text that can be interspersed with the hints.


The "suffix" plus sign Pro*C is using is simply "other commenting text" and ignored as such. It is irrelevant, really.

The starting plus sign tells Oracle that somewhere within this comment (either from /* to */ or from -- to end-of-line) is one or more hints, so it will look for valid hints. Any other text within the comment (invalid hints or garbage or "hi there" or superfluous + signs) are just ignored. This is documented ;-)

Tom Kyte
January 10, 2014 - 5:51 pm UTC

excellent, thanks much!

More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library