Global Hints

Occasionally I encounter a situation when I need to affect a part of the plan that corresponds to a view, e.g.:

select *
   select v.x, x.y
   from v
) q
where q.x = 1

Such situations are resolved using global hints. Oracle offers two ways to specify a global hint: via a query block identifier (system generated or user defined) or via view aliases. System-generated query block identifiers can be obtained via dbms_xplan.display with ALL or ALIAS option (they have the form SEL$n, where n appears to be same as the depth, e.g. in our case 1 corresponds to the main query, 2 to the inline view, 3 to the view V inside that inline view) or defined by the user via qb_name hint.

In our example table T can be addressed either as T@SEL$3 or as q.v.t, e.g.:

select --+ full(t@sel$3)
   select v.x, v.y
   from v
) q
where q.x = 1;

According to official documentation, the two ways of specifying global hints are in principle equivalent, but the SEL$n format is preferrable because with the view alias syntax, Oracle ignores the hint if several query blocks are listed (see for details).

However, a couple of days ago I found that there are problems with this syntax as well. I used the global FULL hint in a query which looked like this:

select /*+full(t1@sel$2)*/ * from v1;

where v1 was defined as

select *
from t1,
     (select ... from t11) q1,
     (select ... from t12) q2
where ...

I tested it, and everything was working perfectly: despite the higher cost, the hint made the optimizer choose the full table scan over an index access path (that was an Exadata system, so despite the higher cost the full table scan was in fact much more efficient). However, later on, under a different user, the query fell back to the original plan.

I looked at 10053 trace file and it contained the following section (line 5 is was in the trace file of the good plan, line 6 was in that of the bad plan, the rest was the same for both):

  signature (): qb_name=SEL$2 nbfros=12 flg=0
    fro(0): flg=5 objn=3179400 hint_alias="T1"@"SEL$2" <-- good plan
    fro(0): flg=5 objn=0 hint_alias="T1"@"SEL$2"       <-- bad plan
    fro(1): flg=4 objn=3179490 hint_alias="T2"@"SEL$2"
    fro(2): flg=4 objn=3179443 hint_alias="T3"@"SEL$2"
    fro(3): flg=4 objn=3179443 hint_alias="T4"@"SEL$2"
    fro(4): flg=4 objn=3179443 hint_alias="T5"@"SEL$2"
    fro(5): flg=4 objn=3179443 hint_alias="T6"@"SEL$2"
    fro(6): flg=4 objn=3177552 hint_alias="T7"@"SEL$2"
    fro(7): flg=4 objn=3179473 hint_alias="T8"@"SEL$2"
    fro(8): flg=4 objn=3177552 hint_alias="T7"@"SEL$2"
    fro(9): flg=4 objn=3179473 hint_alias="T8"@"SEL$2"
    fro(10): flg=5 objn=0 hint_alias="Q1"@"SEL$2"
    fro(11): flg=5 objn=0 hint_alias="Q2"@"SEL$2"

The trace file for the bad plan also contained the lines below:

Registered qb: SEL$3 0xff606118 (PARSER)
 signature (): qb_name=SEL$3 nbfros=1 flg=0
 fro(0): flg=4 objn=3189793 hint_alias="TRADE"@"SEL$3"

It looks like the reason for the global hint being ignored was the failure to recognize T1 as a table — rather, it was treated the same way as subqueries q1 and q2 (objn=0, whereas for successfully resolved tables objn was set to the dba_objects.object_id; also, flg was set to 5 for T1 and the two subqueries, while for successfully resolved tables it was set to 4, although I’m not sure of the actual meaning of this field).

I’m not sure why this object resolution problem occured, and more interestingly why it occured only to T1 of all tables — if readers have any ideas, they are warmly welcome.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s