How could predicate pushing on an inline view slow down a query?
-
20-08-2019 - |
Question
I have inherited a somewhat messy query that I am working on refactoring to be performant.
During this process, one of the things I did due to personal preference was change all of the ANSI-99 join syntax from the "inner join" and "left outer join" statements to be predicates in the query. I noticed two very strange things that I would appreciate an explanation on.
- Changing the joins from the "INNER JOIN..." syntax has changed the explain plan. With the ANSI 99 syntax, oracle did full table scans on the columns that were being joined. After changing the join syntax, it now does predicate pushing. Why would the join syntax change the explain plan?
- The predicate pushing on the inline view has actually slowed down the query by a very significant margin. The query that was running (prior to altering the joins) at around 3 sec. Now it is taking 9 sec. To be honest, I fairly new to reading explain plans so it's entirely possible that the restructuring of the query has slowed it down for a different reason. But ultimately my question is: "Is it possible for predicate pushing on indexed columns to slow down a query so substantially? If so, why?"
Thanks for the replies, and my apologies if this isn't very clear...
Solution
Is it possible for predicate pushing on indexed columns to slow down a query so substantially? If so, why?
Sure it is.
As a rule, predicate pushing makes the optimizer to choose NESTED LOOPS
instead of HASH JOIN
.
This can be slower if the condition is not selective.
This query
SELECT *
FROM table1, t1
(
SELECT /*+ NO_PUSH_PRED */
*
FROM table2 t2
WHERE t2.col1 = :value1
) t2o
WHERE t2o.col2 = t1.col2
most probably will build a hash table over the contents of table1
and will probe the rows returned by the view against this hash table (or vice versa).
This query:
SELECT *
FROM table1, t1
(
SELECT /*+ PUSH_PRED */
*
FROM table2 t2
WHERE t2.col1 = :value1
) t2o
WHERE t2o.col2 = t1.col2
will use the NESTED LOOPS
and an index on (t2.col1, t2.col2)
if it's defined.
The latter is more efficient if col2
is selective on table2
, and less efficient if it's not.
My educated guess is that is exactly what's happening in your case.
If you post your queries and execution plans, I probably will be able to tell more.