Different Plans for Literal Vs Bind Variables
- From: Ian MacGregor <ian@xxxxxxxxxxxxxxxxx>
- To: Oracle-L Freelists <oracle-l@xxxxxxxxxxxxx>
- Date: Fri, 09 Jan 2009 14:22:08 -0800
These two statements have different explain plans
SELECT MAX(B.EFFDT) FROM PS_DEPT_SCRTY_VW B
WHERE B.SETID='SLAC' AND B.EFFDT<=TO_DATE('2008-01-08','YYYY-MM-DD');
And
SELECT MAX(B.EFFDT) FROM PS_DEPT_SCRTY_VW B
WHERE B.SETID=:A1 AND B.EFFDT<=TO_DATE(:A2,'YYYY-MM-DD');
It is not because the second statement is in the library cache. The query
is new. Also a level 12 10046 trace confirmed this.
The problem is that Oracle is not handling the :A2 substitution well.
The statement with the literals is faster. Here is its plan
Rows Row Source Operation
------- ---------------------------------------------------
1 SORT AGGREGATE (cr=74 pr=0 pw=0 time=122348 us)
6007 VIEW (cr=74 pr=0 pw=0 time=120300 us)
6007 FILTER (cr=74 pr=0 pw=0 time=114287 us)
11224 HASH GROUP BY (cr=74 pr=0 pw=0 time=113493 us)
15818 HASH JOIN (cr=74 pr=0 pw=0 time=57310 us)
891 INDEX FAST FULL SCAN IDX$$_7D3D0001 (cr=7 pr=0 pw=0 time=1182
us)(object id 239414)
11240 HASH JOIN (cr=67 pr=0 pw=0 time=15946 us)
894 INDEX FAST FULL SCAN IDX$$_7D3D0001 (cr=7 pr=0 pw=0 time=1092
us)(object id 239414)
6029 INDEX RANGE SCAN PSAPSTREENODE (cr=60 pr=0 pw=0 time=6118
us)(object id 84565)
It's resource usage
call count cpu elapsed disk query current
rows
------- ------ -------- ---------- ---------- ---------- ----------
----------
Parse 1 0.15 0.14 0 2 0
0
Execute 1 0.00 0.00 0 0 0
0
Fetch 2 0.12 0.12 0 74 0
1
------- ------ -------- ---------- ---------- ---------- ----------
----------
total 4 0.27 0.26 0 76 0
1
And waits
Elapsed times include waiting on following events:
Event waited on Times Max. Wait Total
Waited
---------------------------------------- Waited ----------
------------
SQL*Net message to client 2 0.00
0.00
SQL*Net message from client 2 2.58
2.58
----------------------------------------------------------------------------
For the query using bind variables:
The plan
Rows Row Source Operation
------- ---------------------------------------------------
1 SORT AGGREGATE (cr=2000432 pr=37563 pw=37441 time=52938101 us)
6007 NESTED LOOPS (cr=2000432 pr=37563 pw=37441 time=52278837 us)
2000246 HASH JOIN (cr=184 pr=37557 pw=37441 time=39994374 us)
2000246 VIEW VW_SQ_1 (cr=124 pr=27911 pw=27795 time=18708123 us)
2000246 HASH GROUP BY (cr=124 pr=27911 pw=27795 time=18708117 us)
2867021 MERGE JOIN (cr=124 pr=116 pw=0 time=3032698 us)
891 SORT JOIN (cr=16 pr=13 pw=0 time=40303 us)
891 INDEX FAST FULL SCAN PS1DEPT_TBL (cr=16 pr=13 pw=0
time=14728 us)(object id 116752)
2867021 SORT JOIN (cr=108 pr=103 pw=0 time=3002303 us)
6029 INDEX FAST FULL SCAN PSFPSTREENODE (cr=108 pr=103 pw=0
time=6697 us)(object id 84569)
6029 INDEX RANGE SCAN PSAPSTREENODE (cr=60 pr=0 pw=0 time=149
us)(object id 84565)
6007 INDEX UNIQUE SCAN PS_DEPT_TBL (cr=2000248 pr=6 pw=0 time=11796643
us)(object id 116750)
The resource usage
call count cpu elapsed disk query current
rows
------- ------ -------- ---------- ---------- ---------- ----------
----------
Parse 1 0.00 0.00 0 0 0
0
Execute 1 0.21 0.20 0 0 0
0
Fetch 2 38.18 52.93 37563 2000432 0
1
------- ------ -------- ---------- ---------- ---------- ----------
----------
total 4 38.39 53.14 37563 2000432 0
1
And the waits
Elapsed times include waiting on following events:
Event waited on Times Max. Wait Total
Waited
---------------------------------------- Waited ----------
------------
SQL*Net message to client 2 0.00
0.00
db file sequential read 8 0.02
0.06
db file scattered read 16 0.03
0.14
direct path write temp 3231 0.09
16.14
direct path read temp 3231 0.02
1.68
SQL*Net message from client 2 48.93
48.93
----------------------------------------------------------------------------
This apparent problem with the date bind variable while a nuisance in the
example cripples the server when the actual query is run. That query is
SELECT /*+ FIRST_ROWS */ SETID, DEPTID, DESCR FROM PS_DEPT_SCRTY_VW A
WHERE SETID=:1 AND EFFDT= (SELECT MAX(B.EFFDT) FROM PS_DEPT_SCRTY_VW B
WHERE B.SETID=A.SETID AND B.EFFDT<=TO_DATE(:2,'YYYY-MM-DD')) ORDER BY
SETID, DEPTID
The query is generated by PeopleSoft. If both variables are replaced by
literals or just the bind variable ":2" the query runs fine. If the :2 bind
variable is used instead of a literal, the query takes a great deal of time.
How does one get around this problem?
Ian MacGregor
SLAC National Accelerator Laboratory
--
http://www.freelists.org/webpage/oracle-l
Other related posts: