Database Reference
In-Depth Information
Bind Variables Trap
The most common mistake I come across in using the EXPLAIN PLAN statement is to specify a SQL statement that is
different from the one to be analyzed. Naturally, that could lead to the wrong execution plan. Because the formatting
itself has no impact on the execution plan, the difference is usually caused by replacing bind variables. Let's examine
the execution plan used by the query in the following PL/SQL procedure:
CREATE OR REPLACE PROCEDURE p (p_value IN NUMBER) IS
BEGIN
FOR i IN (SELECT * FROM emp WHERE empno = p_value)
LOOP
NULL; -- do something
END LOOP;
END;
A commonly used technique is to copy/paste the query by replacing the PL/SQL variable with a literal. You
execute a SQL statement like this:
EXPLAIN PLAN FOR SELECT * FROM emp WHERE empno = 7788
The problem is that by replacing the bind variable with a literal, you submit a different SQL statement to the
query optimizer. This change—because, for example, of the presence of SQL profiles, stored outlines, SQL plan
baselines (more about these topics in Chapter 11), or the method used by the query optimizer to estimate the
selectivity of the predicate used in the WHERE clause (literals and bind variables aren't handled in the same way)—
might have an impact on the decisions taken by the query optimizer.
The correct approach is to use the same SQL statement. This is possible because bind variables can be used with
the EXPLAIN PLAN statement. You should, as an example, execute a SQL statement like the following one (notice that
the p_value PL/SQL variable was replaced by the :B1 bind variable because this is what the PL/SQL engine would do):
EXPLAIN PLAN FOR SELECT * FROM emp WHERE empno = :B1
Nonetheless, using bind variables with the EXPLAIN PLAN statement has two problems. The first is that, by
default, bind variables are declared as VARCHAR2 . As a result, the database engine might automatically add implicit
conversions, and that could change the execution plan. You can check this with the information about predicates
shown at the end of the output generated by the display function in the dbms_xplan package. In the following output
example, the to_number function is used for that purpose:
SQL> SELECT * FROM table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------
Plan hash value: 4024650034
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 38 | 1 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| EMP | 1 | 38 | 1 (0)| 00:00:01 |
|* 2 | INDEX UNIQUE SCAN | EMP_PK | 1 | | 0 (0)| 00:00:01 |
--------------------------------------------------------------------------------------
 
Search WWH ::




Custom Search