Spent several hours practicing my Introduction to SQL Tuning talk yesterday and it has made me think through the things I’m saying. I don’t want to lead anyone astray by my talk, or the things I’ve posted on this blog. I’ve found something about the use_nl and use_hash hints that I’ve misunderstood for some time. I thought that these hints specified both the outer and inner tables in the join. Another way to say this is the left and right table in the join. But, according to the documentation and my testing these hints really do work on the inner table of the join only.
In my example, which I used in the paper and the slides I wanted the join order to be sales, products, customers but sales and products to be a hash join and the join to customers to be a nested loops. Here are the hints I used to force this join order and join methods:
/*+ leading(sales products) use_hash(sales products) use_nl(products customers) */
Here is the plan:
----------------------------------------- | Id | Operation | Name | ----------------------------------------- | 0 | SELECT STATEMENT | | | 1 | NESTED LOOPS | | |* 2 | HASH JOIN | | |* 3 | TABLE ACCESS FULL| SALES | |* 4 | TABLE ACCESS FULL| PRODUCTS | |* 5 | TABLE ACCESS FULL | CUSTOMERS | -----------------------------------------
Now this is the right plan and I think that is why it is so confusing. But you can accomplish the same thing by just listing the intended inner tables – products for the hash join and customers for the nested loops join. Here is the simplified and correct hint – which produces the same plan:
/*+ leading(sales products) use_hash(products) use_nl(customers) */
Just to prove these really are the inner tables I tried using sales in the hash join hint and products in the use_nl hint:
/*+ leading(sales products) use_hash(sales) use_nl(products) */ ----------------------------------------- | Id | Operation | Name | ----------------------------------------- | 0 | SELECT STATEMENT | | |* 1 | HASH JOIN | | | 2 | NESTED LOOPS | | |* 3 | TABLE ACCESS FULL| SALES | |* 4 | TABLE ACCESS FULL| PRODUCTS | |* 5 | TABLE ACCESS FULL | CUSTOMERS | -----------------------------------------
Notice that now we use a nested loops join with products as the inner table and sales as the outer table. Sales can’t be the inner table of a join because of the leading hint so the use_hash hint is ignored and customers is the inner table of the hash join which is just something the optimizer chose on its own.
So, bottom line is when you are specifying use_hash or use_nl hints only list the inner or right table of your join.
– Bobby