Re: Explain Plan and Security

  • From: Andy Klock <andy@xxxxxxxxxxxxxxx>
  • To: Jonathan Lewis <jonathan@xxxxxxxxxxxxxxxxxx>
  • Date: Thu, 14 Jun 2018 13:37:57 -0400

Fair enough Jonathan. I was just referring to the OP's original concern
with the explain plan lying to you (with Kerry's example of it ignoring
bind variables). But, to yours and Mauro's point, and admittedly it does
take me longer to evenually catch up, it does appear that EXPLAIN_PLAN and
DBMS_SQL(PARSE/BIND/DESCIBE) behave similarly in regards to BINDs. Though,
I was actually  expecting an INDEX scan with my DBMS_SQL.EXECUTE but it
still opted for a FULL, so I'd have to dig a little deeper to figure out
why.

EXPLAIN PLAN:

SQL> var n number
SQL> exec :n:=2

PL/SQL procedure successfully completed.

SQL> explain plan for select /* EXPLAIN PLAN TEST WITH BIND 2 */ * from
parse_test where n = :n;

Explained.

SQL> select plan_table_output from table(dbms_xplan.display('
plan_table',null,'basic'));

PLAN_TABLE_OUTPUT
------------------------------------------------------------
------------------------------------------------------------
------------------------------
Plan hash value: 464636435

----------------------------------------
| Id  | Operation   | Name       |
----------------------------------------
|   0 | SELECT STATEMENT  |        |
|   1 |  TABLE ACCESS FULL| PARSE_TEST |
----------------------------------------

8 rows selected.

DBMS_SQL.EXECUTE

SQL> DECLARE
 cursor_name    INTEGER;
 rows_processed INTEGER;
BEGIN
  cursor_name := dbms_sql.open_cursor;
  dbms_sql.parse(cursor_name, 'select /* SQL_PARSE TEST BIND EXECUTE 2 */ *
from parse_test where n = :n', dbms_sql.NATIVE);
  dbms_sql.bind_variable(cursor_name, ':n', 2);
  rows_processed := dbms_sql.execute(cursor_name);
  dbms_sql.close_cursor(cursor_name);
END;
/

PL/SQL procedure successfully completed.

SQL> @findsq EXECUTE

SQL_ID       PLAN_HASH_VALUE LENGTH(SQL_FULLTEXT) SUB_TEXT       EXECUTIONS
AVG_ELAPSED
------------- --------------- --------------------
-------------------------------------------------- ---------- -----------
488vjz6gr04r3     0        369 DECLARE  cursor_name    INTEGER;
rows_processed I        1      .01316
c7s8yq1atczdx     464636435 73 select /* SQL_PARSE TEST BIND EXECUTE 2 */ *
from        1     .003964

SQL> @dplan
Enter value for sql_id: c7s8yq1atczdx
Enter value for child_no:

PLAN_TABLE_OUTPUT
------------------------------------------------------------
-----------------------------------------------------------------
SQL_ID c7s8yq1atczdx, child number 0
-------------------------------------
select /* SQL_PARSE TEST BIND EXECUTE 2 */ * from parse_test where n =
:n

Plan hash value: 464636435

------------------------------------------------------------
---------------------
| Id  | Operation   | Name       | E-Rows |E-Bytes| Cost (%CPU)| E-Time |
------------------------------------------------------------
---------------------
|   0 | SELECT STATEMENT  |        | | |     9 (100)| |
|*  1 |  TABLE ACCESS FULL| PARSE_TEST |  12501 |   109K|     9   (0)|
00:00:01 |
------------------------------------------------------------
---------------------


EXECUTING:

SQL> select /* EXECUTE! TEST */ * from parse_test where n = :n;

N C
---------- ----------
2 GARCIA

SQL> @findsq EXECUTE!

SQL_ID       PLAN_HASH_VALUE LENGTH(SQL_FULLTEXT) SUB_TEXT       EXECUTIONS
AVG_ELAPSED
------------- --------------- --------------------
-------------------------------------------------- ---------- -----------
ammqtfmhv5tpk    2679036580 57 select /* EXECUTE! TEST */ * from parse_test
where        1     .008336


SQL> @dplan
Enter value for sql_id: ammqtfmhv5tpk
Enter value for child_no:

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID ammqtfmhv5tpk, child number 0
-------------------------------------
select /* EXECUTE! TEST */ * from parse_test where n = :n

Plan hash value: 2679036580

-------------------------------------------------------------------------------------------------------
| Id  | Operation     | Name      | E-Rows |E-Bytes| Cost (%CPU)| E-Time   |
-------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |      |       |       |     2 (100)|       |
|   1 |  TABLE ACCESS BY INDEX ROWID BATCHED| PARSE_TEST     |     1 |
 9 |     2 (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN     | PARSE_TEST_IND |     1 |       |     1 (0)|
00:00:01 |
-------------------------------------------------------------------------------------------------------

Thanks,

Andy K


On Thu, Jun 14, 2018 at 1:01 PM, Jonathan Lewis <jonathan@xxxxxxxxxxxxxxxxxx

wrote:


Andy,

I don't think I'd even be that generous. I can't think of any detail where
dbms_sql/dbms_xplan.display_cursor() gives you safer information than
explain plan / dbms_xplan.display().
I suppose the extra complexity of using dbms_sql might make you a little
more careful as you set up a test, and that could be a benefit.

Regards
Jonathan Lewis


________________________________________
From: andyklock@xxxxxxxxx <andyklock@xxxxxxxxx> on behalf of Andy Klock <
andy@xxxxxxxxxxxxxxx>
Sent: 14 June 2018 17:15
To: Jonathan Lewis
Cc: oracle-l@xxxxxxxxxxxxx
Subject: Re: Explain Plan and Security

Ah! Indeed. Thanks for that Jonathan. So, the takeaway is that DBMS_SQL is
slightly better than EXPLAIN PLAN. But, only slightly?

Thanks!

Andy K

On Thu, Jun 14, 2018 at 12:08 PM, Jonathan Lewis <
jonathan@xxxxxxxxxxxxxxxxxx<mailto:jonathan@xxxxxxxxxxxxxxxxxx>> wrote:

Andy,

If you add a "describe columns" to your SQL PARSE TEST BIND you find that
you do get a plan before the execute.



Other related posts: