Question on Tuning SQL query
We are converting from a 9i database to an 11g database. The query defined works perfectly under 9i (about 1 second) but is taking 60-70 seconds to return in 11g. The wierd thing is that it has an outer query and a subquery. If I remove the where clause from the outer query it executes in less than a second. Here is the query...
SELECT period, biweek_start, biweek_end, pay_period_complete, worker_count
FROM (SELECT to_char(en.start_date, 'yyyy/mm/dd') || ' to ' ||
to_char(en.start_date + 13, 'yyyy/mm/dd') period,
en.start_date biweek_start,
en.start_date + 13 biweek_end,
decode(sign(sysdate - en.start_date - 13),
-1,
'In Progress',
'Completed') pay_period_complete,
ta_mssauth_pkg.actual_endorser(en.start_date, '33811') worker_count
FROM (select worker_id,
default_endorser resolved_endorser,
effective_date,
expiration_date
from endorse_delegate_history_v
where default_endorser = '33811'
union
select worker_id,
temporary_delegate resolved_endorser,
effective_date,
expiration_date
from endorse_delegate_history_v
where temporary_delegate = '33811'
and temporary_delegate is not null ) de,
endorse_activity_v en
WHERE en.worker_id = de.worker_id
AND en.endorse_status = 'N'
AND en.start_date <= de.expiration_date
AND en.start_date + 13 >= de.effective_date
GROUP BY en.start_date)
WHERE worker_count > 0;
The function that is used as part of the inner query to generate worker_counts is pretty complex. But it runs subsecond if you run it manually. And it works great when you run the query without the "where worker_count > 0" portion.
So the where clause on the outer query seems to be causing the problem - it is based off a function that should have calculated a value FIRST then the outer query should run based on the result of the inner query. Below are the explain plans for the two different versions:
BAD QUERY - 60 - 70 Seconds
Description Object Owner Object Name Cost Cardinality Bytes
SELECT STATEMENT, GOAL = ALL_ROWS 617 1 41
HASH GROUP BY 617 1 41
NESTED LOOPS
NESTED LOOPS 616 1 41
VIEW CA17062 58 186 4464
SORT UNIQUE 58 186 5392
UNION-ALL
TABLE ACCESS BY INDEX ROWID TAS_AUTH ENDORSE_DELEGATE_HISTORY_TBL 42 139 4170
INDEX RANGE SCAN TAS_AUTH ENDORSE_DELEGATE_HIST_DEF_IDX 3 139
TABLE ACCESS BY INDEX ROWID TAS_AUTH ENDORSE_DELEGATE_HISTORY_TBL 14 47 1222
INDEX RANGE SCAN TAS_AUTH ENDORSE_DELEGATE_HIST_TEMP_IDX 3 47
INDEX RANGE SCAN TAS_AUTH TA_SCLENDORSE_PK 2 1
TABLE ACCESS BY INDEX ROWID TAS_AUTH ENDORSE_ACTIVITY_TBL 3 1 17
GOOD QUERY < 1 second
Description Object Owner Object Name Cost Cardinality Bytes
SELECT STATEMENT, GOAL = ALL_ROWS 617 25 1025
HASH GROUP BY 617 25 1025
NESTED LOOPS
NESTED LOOPS 616 25 1025
VIEW CA17062 58 186 4464
SORT UNIQUE 58 186 5392
UNION-ALL
TABLE ACCESS BY INDEX ROWID TAS_AUTH ENDORSE_DELEGATE_HISTORY_TBL 42 139 4170
INDEX RANGE SCAN TAS_AUTH ENDORSE_DELEGATE_HIST_DEF_IDX 3 139
TABLE ACCESS BY INDEX ROWID TAS_AUTH ENDORSE_DELEGATE_HISTORY_TBL 14 47 1222
INDEX RANGE SCAN TAS_AUTH ENDORSE_DELEGATE_HIST_TEMP_IDX 3 47
INDEX RANGE SCAN TAS_AUTH TA_SCLENDORSE_PK 2 1
TABLE ACCESS BY INDEX ROWID TAS_AUTH ENDORSE_ACTIVITY_TBL 3 1 17
So those expleain plans look pretty much identical to me - can anyone tell me why having the where clause on the outer query is causing so much trouble and how I can fix it? I've tried using NO_MERGE and PUSH_SUBQ hints - but nothing that I have done has made the bad query any better.
Thanks in advance!
Cory
I have traced the queries and attached the trace files here too...
Here is the bad query...
SQL ID: 0g07hqvjma217 Plan Hash: 0
alter session set sql_trace = true
call count cpu elapsed disk query current rows
Parse 0 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 0 0.00 0.00 0 0 0 0
total 1 0.00 0.00 0 0 0 0
Misses in library cache during parse: 0
Misses in library cache during execute: 1
Optimizer mode: ALL_ROWS
Parsing user id: 331 (CA17062)
SQL ID: 9m7787camwh4m Plan Hash: 0
begin :id := sys.dbms_transaction.local_transaction_id; end;
call count cpu elapsed disk query current rows
Parse 3 0.00 0.00 0 0 0 0
Execute 3 0.00 0.00 0 0 0 3
Fetch 0 0.00 0.00 0 0 0 0
total 6 0.00 0.00 0 0 0 3
Misses in library cache during parse: 0
Optimizer mode: ALL_ROWS
Parsing user id: 331 (CA17062)
SELECT period, biweek_start, biweek_end, pay_period_complete, worker_count
FROM (SELECT to_char(en.start_date, 'yyyy/mm/dd') || ' to ' ||
to_char(en.start_date + 13, 'yyyy/mm/dd') period,
en.start_date biweek_start,
en.start_date + 13 biweek_end,
decode(sign(sysdate - en.start_date - 13),
-1,
'In Progress',
'Completed') pay_period_complete,
ta_mssauth_pkg.actual_endorser(en.start_date, '33811') worker_count
FROM (select worker_id,
default_endorser resolved_endorser,
effective_date,
expiration_date
from endorse_delegate_history_v
where default_endorser = '33811'
union
select worker_id,
temporary_delegate resolved_endorser,
effective_date,
expiration_date
from endorse_delegate_history_v
where temporary_delegate = '33811'
and temporary_delegate is not null ) de,
endorse_activity_v en
WHERE en.worker_id = de.worker_id
AND en.endorse_status = 'N'
AND en.start_date <= de.expiration_date
AND en.start_date + 13 >= de.effective_date
GROUP BY en.start_date)
WHERE worker_count > 0
call count cpu elapsed disk query current rows
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 1 6.11 14.77 38 455 0 6
total 3 6.11 14.77 38 455 0 6
Misses in library cache during parse: 0
Optimizer mode: ALL_ROWS
Parsing user id: 331 (CA17062)
Number of plan statistics captured: 1
Rows (1st) Rows (avg) Rows (max) Row Source Operation
6 6 6 HASH GROUP BY (cr=9330657 pr=826 pw=0 time=86392712 us cost=698 size=41 card=1)
21 21 21 NESTED LOOPS (cr=9330657 pr=826 pw=0 time=18442971 us)
49 49 49 NESTED LOOPS (cr=9330609 pr=826 pw=0 time=26482026 us cost=697 size=41 card=1)
213 213 213 VIEW (cr=32 pr=32 pw=0 time=851827 us cost=58 size=5112 card=213)
213 213 213 SORT UNIQUE (cr=32 pr=32 pw=0 time=850864 us cost=58 size=5598 card=213)
213 213 213 UNION-ALL (cr=32 pr=32 pw=0 time=4390885 us)
15 15 15 TABLE ACCESS BY INDEX ROWID ENDORSE_DELEGATE_HISTORY_TBL (cr=10 pr=10 pw=0 time=718114 us c)
15 15 15 INDEX RANGE SCAN ENDORSE_DELEGATE_HIST_DEF_IDX (cr=3 pr=3 pw=0 time=119582 us cost=3 size=)
198 198 198 TABLE ACCESS BY INDEX ROWID ENDORSE_DELEGATE_HISTORY_TBL (cr=22 pr=22 pw=0 time=7328583 us )
198 198 198 INDEX RANGE SCAN ENDORSE_DELEGATE_HIST_TEMP_IDX (cr=3 pr=3 pw=0 time=107110 us cost=3 size)
49 49 49 INDEX RANGE SCAN TA_SCLENDORSE_PK (cr=9330577 pr=794 pw=0 time=157121745 us cost=2 size=0 card)
21 21 21 TABLE ACCESS BY INDEX ROWID ENDORSE_ACTIVITY_TBL (cr=48 pr=0 pw=0 time=493 us cost=3 size=17 ca)
Rows Execution Plan
0 SELECT STATEMENT MODE: ALL_ROWS
6 HASH (GROUP BY)
21 NESTED LOOPS
49 NESTED LOOPS
213 VIEW
213 SORT (UNIQUE)
213 UNION-ALL
15 TABLE ACCESS MODE: ANALYZED (BY INDEX ROWID) OF
'ENDORSE_DELEGATE_HISTORY_TBL' (TABLE)
15 INDEX MODE: ANALYZED (RANGE SCAN) OF
'ENDORSE_DELEGATE_HIST_DEF_IDX' (INDEX)
198 TABLE ACCESS MODE: ANALYZED (BY INDEX ROWID) OF
'ENDORSE_DELEGATE_HISTORY_TBL' (TABLE)
198 INDEX MODE: ANALYZED (RANGE SCAN) OF
'ENDORSE_DELEGATE_HIST_TEMP_IDX' (INDEX)
49 INDEX MODE: ANALYZED (RANGE SCAN) OF 'TA_SCLENDORSE_PK'
(INDEX (UNIQUE))
21 TABLE ACCESS MODE: ANALYZED (BY INDEX ROWID) OF
'ENDORSE_ACTIVITY_TBL' (TABLE)
SQL ID: gwpkaabt9naxy Plan Hash: 2668568437
SELECT DISTINCT DE.WORKER_ID
FROM
ENDORSE_DELEGATE_HISTORY_V DE , ENDORSE_ACTIVITY_V EN ,
WORKER_ACTIVITY_AUTH_V EA WHERE DE.WORKER_ID = EN.WORKER_ID AND
EN.WORKER_ID = EA.WORKER_ID AND EN.START_DATE = :B2 AND EN.ENDORSE_STATUS =
'N' AND EA.ACTIVITY_DATE >= EN.START_DATE AND EA.ACTIVITY_DATE <=
EN.START_DATE + 13 AND EN.START_DATE <= DE.EXPIRATION_DATE AND
EN.START_DATE + 13 >= DE.EFFECTIVE_DATE AND (DE.DEFAULT_ENDORSER = :B1 OR
DE.TEMPORARY_DELEGATE = :B1 ) ORDER BY DE.WORKER_ID
call count cpu elapsed disk query current rows
Parse 1 0.00 0.00 0 0 0 0
Execute 24015 0.97 1.50 0 0 0 0
Fetch 24015 56.38 132.62 593 9318744 0 285
total 48031 57.35 134.12 593 9318744 0 285
Misses in library cache during parse: 0
Optimizer mode: ALL_ROWS
Parsing user id: 3054 (TAS_AUTH) (recursive depth: 1)
Number of plan statistics captured: 1
Rows (1st) Rows (avg) Rows (max) Row Source Operation
0 0 0 SORT UNIQUE (cr=407 pr=43 pw=0 time=1057475 us cost=805 size=83 card=1)
0 0 0 NESTED LOOPS (cr=407 pr=43 pw=0 time=1057453 us cost=804 size=17347 card=209)
0 0 0 HASH JOIN RIGHT ANTI (cr=407 pr=43 pw=0 time=1057442 us cost=804 size=16511 card=209)
19 19 19 INDEX RANGE SCAN INDACC_02X (cr=1 pr=0 pw=0 time=78 us cost=1 size=114 card=19)(object id 5403)
0 0 0 NESTED LOOPS (cr=406 pr=43 pw=0 time=1055235 us)
0 0 0 NESTED LOOPS (cr=406 pr=43 pw=0 time=1055231 us cost=803 size=19856 card=272)
0 0 0 NESTED LOOPS (cr=406 pr=43 pw=0 time=1055226 us cost=431 size=350 card=7)
186 186 186 TABLE ACCESS BY INDEX ROWID ENDORSE_DELEGATE_HISTORY_TBL (cr=32 pr=0 pw=0 time=4375 us cost)
213 213 213 BITMAP CONVERSION TO ROWIDS (cr=6 pr=0 pw=0 time=759 us)
1 1 1 BITMAP OR (cr=6 pr=0 pw=0 time=533 us)
1 1 1 BITMAP CONVERSION FROM ROWIDS (cr=3 pr=0 pw=0 time=178 us)
15 15 15 SORT ORDER BY (cr=3 pr=0 pw=0 time=152 us)
15 15 15 INDEX RANGE SCAN ENDORSE_DELEGATE_HIST_DEF_IDX (cr=3 pr=0 pw=0 time=62 us cost=3 size=)
1 1 1 BITMAP CONVERSION FROM ROWIDS (cr=3 pr=0 pw=0 time=328 us)
198 198 198 SORT ORDER BY (cr=3 pr=0 pw=0 time=319 us)
198 198 198 INDEX RANGE SCAN ENDORSE_DELEGATE_HIST_TEMP_IDX (cr=3 pr=0 pw=0 time=214 us cost=3 siz)
0 0 0 TABLE ACCESS BY INDEX ROWID ENDORSE_ACTIVITY_TBL (cr=374 pr=43 pw=0 time=1052137 us cost=2 )
0 0 0 INDEX UNIQUE SCAN TA_SCLENDORSE_PK (cr=374 pr=43 pw=0 time=1051749 us cost=1 size=0 card=1)
0 0 0 INDEX RANGE SCAN WORKER_ACTIVITY_WRKR_IX (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=90)(ob)
0 0 0 TABLE ACCESS BY INDEX ROWID WORKER_ACTIVITY_TBL (cr=0 pr=0 pw=0 time=0 us cost=53 size=943 ca)
0 0 0 INDEX UNIQUE SCAN SCHEDULE_PK (cr=0 pr=0 pw=0 time=0 us cost=0 size=4 card=1)(object id 54342)
Rows Execution Plan
0 SELECT STATEMENT MODE: ALL_ROWS
0 SORT (UNIQUE)
0 CONCATENATION
0 NESTED LOOPS (ANTI)
19 NESTED LOOPS
0 NESTED LOOPS
0 NESTED LOOPS
0 TABLE ACCESS MODE: ANALYZED (BY INDEX ROWID) OF
'ENDORSE_DELEGATE_HISTORY_TBL' (TABLE)
186 INDEX MODE: ANALYZED (RANGE SCAN) OF
'ENDORSE_DELEGATE_HIST_TEMP_IDX' (INDEX)
213 TABLE ACCESS MODE: ANALYZED (BY INDEX ROWID) OF
'ENDORSE_ACTIVITY_TBL' (TABLE)
1 INDEX MODE: ANALYZED (UNIQUE SCAN) OF
'TA_SCLENDORSE_PK' (INDEX (UNIQUE))
1 TABLE ACCESS MODE: ANALYZED (BY INDEX ROWID) OF
'WORKER_ACTIVITY_TBL' (TABLE)
15 INDEX MODE: ANALYZED (RANGE SCAN) OF
'WORKER_ACTIVITY_WRKR_IX' (INDEX)
15 INDEX MODE: ANALYZED (UNIQUE SCAN) OF 'SCHEDULE_PK'
(INDEX (UNIQUE))
1 INDEX MODE: ANALYZED (RANGE SCAN) OF 'INDACC_02X' (INDEX)
198 NESTED LOOPS (ANTI)
198 NESTED LOOPS
0 NESTED LOOPS
0 NESTED LOOPS
0 TABLE ACCESS MODE: ANALYZED (BY INDEX ROWID) OF
'ENDORSE_DELEGATE_HISTORY_TBL' (TABLE)
0 INDEX MODE: ANALYZED (RANGE SCAN) OF
'ENDORSE_DELEGATE_HIST_DEF_IDX' (INDEX)
0 TABLE ACCESS MODE: ANALYZED (BY INDEX ROWID) OF
'ENDORSE_ACTIVITY_TBL' (TABLE)
0 INDEX MODE: ANALYZED (UNIQUE SCAN) OF
'TA_SCLENDORSE_PK' (INDEX (UNIQUE))
0 TABLE ACCESS MODE: ANALYZED (BY INDEX ROWID) OF
'WORKER_ACTIVITY_TBL' (TABLE)
0 INDEX MODE: ANALYZED (RANGE SCAN) OF
'WORKER_ACTIVITY_WRKR_IX' (INDEX)
0 INDEX MODE: ANALYZED (UNIQUE SCAN) OF 'SCHEDULE_PK'
(INDEX (UNIQUE))
0 INDEX MODE: ANALYZED (RANGE SCAN) OF 'INDACC_02X' (INDEX)
SQL ID: 7v8ndut1y3b99 Plan Hash: 2002979989
SELECT DEFAULT_ENDORSER
FROM
( SELECT DEFAULT_ENDORSER FROM ENDORSE_DELEGATE_HISTORY_V WHERE WORKER_ID =
:B3 AND TEMPORARY_DELEGATE IS NULL AND :B2 <= EXPIRATION_DATE AND :B1 >=
EFFECTIVE_DATE ORDER BY EXPIRATION_DATE DESC ) WHERE ROWNUM = 1
call count cpu elapsed disk query current rows
Parse 1 0.00 0.00 0 0 0 0
Execute 285 0.00 0.01 0 0 0 0
Fetch 285 0.11 3.24 195 13078 0 285
total 571 0.11 3.26 195 13078 0 285
Misses in library cache during parse: 0
Optimizer mode: ALL_ROWS
Parsing user id: 3054 (TAS_AUTH) (recursive depth: 1)
Number of plan statistics captured: 1
Rows (1st) Rows (avg) Rows (max) Row Source Operation
1 1 1 COUNT STOPKEY (cr=22 pr=20 pw=0 time=576320 us)
1 1 1 VIEW (cr=22 pr=20 pw=0 time=576285 us cost=23 size=72 card=12)
1 1 1 SORT ORDER BY STOPKEY (cr=22 pr=20 pw=0 time=576273 us cost=23 size=396 card=12)
2 2 2 TABLE ACCESS BY INDEX ROWID ENDORSE_DELEGATE_HISTORY_TBL (cr=22 pr=20 pw=0 time=576205 us cost)
20 20 20 INDEX RANGE SCAN ENDORSE_DELEGATE_HIST_PK (cr=3 pr=3 pw=0 time=197569 us cost=3 size=0 card=1)
Rows Execution Plan
0 SELECT STATEMENT MODE: ALL_ROWS
1 COUNT (STOPKEY)
1 VIEW
1 SORT (ORDER BY STOPKEY)
2 TABLE ACCESS MODE: ANALYZED (BY INDEX ROWID) OF
'ENDORSE_DELEGATE_HISTORY_TBL' (TABLE)
20 INDEX MODE: ANALYZED (RANGE SCAN) OF
'ENDORSE_DELEGATE_HIST_PK' (INDEX (UNIQUE))
SQL ID: cf06fwacdmgfk Plan Hash: 1546270724
select 'x'
from
dual
call count cpu elapsed disk query current rows
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 1 0.00 0.00 0 0 0 1
total 3 0.00 0.00 0 0 0 1
Misses in library cache during parse: 0
Optimizer mode: ALL_ROWS
Parsing user id: 331 (CA17062)
Number of plan statistics captured: 1
Rows (1st) Rows (avg) Rows (max) Row Source Operation
1 1 1 FAST DUAL (cr=0 pr=0 pw=0 time=6 us cost=2 size=0 card=1)
Rows Execution Plan
0 SELECT STATEMENT MODE: ALL_ROWS
1 FAST DUAL
OVERALL TOTALS FOR ALL NON-RECURSIVE STATEMENTS
call count cpu elapsed disk query current rows
Parse 5 0.00 0.00 0 0 0 0
Execute 6 0.00 0.00 0 0 0 3
Fetch 2 6.11 14.77 38 455 0 7
total 13 6.11 14.77 38 455 0 10
Misses in library cache during parse: 0
Misses in library cache during execute: 1
OVERALL TOTALS FOR ALL RECURSIVE STATEMENTS
call count cpu elapsed disk query current rows
Parse 2 0.00 0.00 0 0 0 0
Execute 24300 0.97 1.51 0 0 0 0
Fetch 24300 56.49 135.87 788 9331822 0 570
total 48602 57.46 137.39 788 9331822 0 570
Misses in library cache during parse: 0
6 user SQL statements in session.
0 internal SQL statements in session.
6 SQL statements in session.
4 statements EXPLAINed in this session.
Trace file: TAST_ora_26885.trc
Trace file compatibility: 11.1.0.7
Sort options: default
1 session in tracefile.
6 user SQL statements in trace file.
0 internal SQL statements in trace file.
6 SQL statements in trace file.
6 unique SQL statements in trace file.
4 SQL statements EXPLAINed using schema:
dbo.plan_table
Schema was specified.
Existing table was used.
73341 lines in trace file.
178 elapsed seconds in trace file.
Here is the good query
SQL ID: 0g07hqvjma217 Plan Hash: 0
alter session set sql_trace = true
call count cpu elapsed disk query current rows
Parse 0 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 0 0.00 0.00 0 0 0 0
total 1 0.00 0.00 0 0 0 0
Misses in library cache during parse: 0
Misses in library cache during execute: 1
Optimizer mode: ALL_ROWS
Parsing user id: 331 (CA17062)
SQL ID: 9m7787camwh4m Plan Hash: 0
begin :id := sys.dbms_transaction.local_transaction_id; end;
call count cpu elapsed disk query current rows
Parse 3 0.00 0.00 0 0 0 0
Execute 3 0.00 0.00 0 0 0 3
Fetch 0 0.00 0.00 0 0 0 0
total 6 0.00 0.00 0 0 0 3
Misses in library cache during parse: 0
Optimizer mode: ALL_ROWS
Parsing user id: 331 (CA17062)
SELECT period, biweek_start, biweek_end, pay_period_complete, worker_count
FROM (SELECT to_char(en.start_date, 'yyyy/mm/dd') || ' to ' ||
to_char(en.start_date + 13, 'yyyy/mm/dd') period,
en.start_date biweek_start,
en.start_date + 13 biweek_end,
decode(sign(sysdate - en.start_date - 13),
-1,
'In Progress',
'Completed') pay_period_complete,
ta_mssauth_pkg.actual_endorser(en.start_date, '33811') worker_count
FROM (select worker_id,
default_endorser resolved_endorser,
effective_date,
expiration_date
from endorse_delegate_history_v
where default_endorser = '33811'
union
select worker_id,
temporary_delegate resolved_endorser,
effective_date,
expiration_date
from endorse_delegate_history_v
where temporary_delegate = '33811'
and temporary_delegate is not null ) de,
endorse_activity_v en
WHERE en.worker_id = de.worker_id
AND en.endorse_status = 'N'
AND en.start_date <= de.expiration_date
AND en.start_date + 13 >= de.effective_date
GROUP BY en.start_date)
-- WHERE worker_count > 0
call count cpu elapsed disk query current rows
Parse 1 0.02 0.03 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 1 0.02 0.13 0 841 0 6
total 3 0.04 0.16 0 841 0 6
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 331 (CA17062)
Number of plan statistics captured: 1
Rows (1st) Rows (avg) Rows (max) Row Source Operation
6 6 6 HASH GROUP BY (cr=841 pr=0 pw=0 time=79927 us cost=617 size=1025 card=25)
21 21 21 NESTED LOOPS (cr=841 pr=0 pw=0 time=15116 us)
451 451 451 NESTED LOOPS (cr=409 pr=0 pw=0 time=33039 us cost=616 size=1025 card=25)
213 213 213 VIEW (cr=32 pr=0 pw=0 time=12117 us cost=58 size=4464 card=186)
213 213 213 SORT UNIQUE (cr=32 pr=0 pw=0 time=12005 us cost=58 size=5392 card=186)
213 213 213 UNION-ALL (cr=32 pr=0 pw=0 time=1313 us)
15 15 15 TABLE ACCESS BY INDEX ROWID ENDORSE_DELEGATE_HISTORY_TBL (cr=10 pr=0 pw=0 time=245 us cost=4
2 size=4170 card=139)
15 15 15 INDEX RANGE SCAN ENDORSE_DELEGATE_HIST_DEF_IDX (cr=3 pr=0 pw=0 time=122 us cost=3 size=0 ca
rd=139)(object id 54559)
198 198 198 TABLE ACCESS BY INDEX ROWID ENDORSE_DELEGATE_HISTORY_TBL (cr=22 pr=0 pw=0 time=427 us cost=1
4 size=1222 card=47)
198 198 198 INDEX RANGE SCAN ENDORSE_DELEGATE_HIST_TEMP_IDX (cr=3 pr=0 pw=0 time=222 us cost=3 size=0 c
ard=47)(object id 54560)
451 451 451 INDEX RANGE SCAN TA_SCLENDORSE_PK (cr=377 pr=0 pw=0 time=63328 us cost=2 size=0 card=1)(object
id 54553)
21 21 21 TABLE ACCESS BY INDEX ROWID ENDORSE_ACTIVITY_TBL (cr=432 pr=0 pw=0 time=2185 us cost=3 size=17 c
ard=1)
Rows Execution Plan
0 SELECT STATEMENT MODE: ALL_ROWS
6 HASH (GROUP BY)
21 NESTED LOOPS
451 NESTED LOOPS
213 VIEW
213 SORT (UNIQUE)
213 UNION-ALL
15 TABLE ACCESS MODE: ANALYZED (BY INDEX ROWID) OF
'ENDORSE_DELEGATE_HISTORY_TBL' (TABLE)
15 INDEX MODE: ANALYZED (RANGE SCAN) OF
'ENDORSE_DELEGATE_HIST_DEF_IDX' (INDEX)
198 TABLE ACCESS MODE: ANALYZED (BY INDEX ROWID) OF
'ENDORSE_DELEGATE_HISTORY_TBL' (TABLE)
198 INDEX MODE: ANALYZED (RANGE SCAN) OF
'ENDORSE_DELEGATE_HIST_TEMP_IDX' (INDEX)
451 INDEX MODE: ANALYZED (RANGE SCAN) OF 'TA_SCLENDORSE_PK'
(INDEX (UNIQUE))
21 TABLE ACCESS MODE: ANALYZED (BY INDEX ROWID) OF
'ENDORSE_ACTIVITY_TBL' (TABLE)
SQL ID: gwpkaabt9naxy Plan Hash: 2668568437
SELECT DISTINCT DE.WORKER_ID
FROM
ENDORSE_DELEGATE_HISTORY_V DE , ENDORSE_ACTIVITY_V EN ,
WORKER_ACTIVITY_AUTH_V EA WHERE DE.WORKER_ID = EN.WORKER_ID AND
EN.WORKER_ID = EA.WORKER_ID AND EN.START_DATE = :B2 AND EN.ENDORSE_STATUS =
'N' AND EA.ACTIVITY_DATE >= EN.START_DATE AND EA.ACTIVITY_DATE <=
EN.START_DATE + 13 AND EN.START_DATE <= DE.EXPIRATION_DATE AND
EN.START_DATE + 13 >= DE.EFFECTIVE_DATE AND (DE.DEFAULT_ENDORSER = :B1 OR
DE.TEMPORARY_DELEGATE = :B1 ) ORDER BY DE.WORKER_ID
call count cpu elapsed disk query current rows
Parse 1 0.00 0.00 0 0 0 0
Execute 6 0.01 0.00 0 0 0 0
Fetch 6 0.01 0.01 0 700
Similar Messages
-
Please help me in tuning this query. This view has around 2 million of records
SELECT * FROM employee_v
WHERE status_id IN (SELECT MAX(v2.status_id)status_id
FROM employee_v v2
WHERE UPPER(v2.name) LIKE UPPER(:v_name)||'%'
GROUP BY v2.emp_id, v2.project_id)
ORDER BY status_type_id;
Here:
employees may work on one or more projects
employee working on a given project may have one or more status_ids associated.
for example:
emp_id project_id status_id
10 100 1
10 100 2
20 100 2
20 200 3
30 100 4
30 200 5
30 200 6
40 200 6
If you have any other suggestions , please let me know too. For example, I was thinking that the subquery should use actual tables instead of the view because view is based on 10 tables and the subquery can instead use two tables . Does it make sense?
Thanks a lot for the help!
Edited by: user5406804 on Apr 20, 2010 5:42 AMIf you have any other suggestions , please let me know too. Wild shot in the dark, but maybe using EXISTS instead of IN speeds up your query:
untested for obvious reasons
select *
from employee_v v
where upper(v.name) like upper(:v_name)||'%'
where not exists ( select null
from employee_v v2
and v2.status_id > v.status_id
and v2.emp_id = v.emp_id -- assuming you have some emp_id PK column
-- if necessary, you need to change the name of this column ofcourse
order by status_type_id;Do compare the resultsets, not sure this will give you the same/desired result, but it might give you an idea.
For example, I was thinking that the subquery should use actual tables instead of the view because > view is based on 10 tables and the subquery can instead
use two tables . Does it make sense?Sounds like worth a try to me, yes. Less data to plough through = faster response.
As well as using a function based index on UPPER(name) might be worth a try. -
Tuning SQL Query calling multiple views
Dear All,
I have a complex scenario in which I have created views in 3 levels for sales and Service separately so total no of views are 6.
Level 2 calls view in Level 1 and Level 3 calls level 2 in sales as well as services.
Finally Level 4 has the union of sales and Service Level 3 view.
There are 5 tables used in total and all have been indexed for better performance.
The cube processing for the above scenario has processing time of 6 mins.
The goal is to bring it down to 2-3 mins.
The amount of data currently we are looking at is not more than 2-3 GB.
Can anybody help me fine tune this scenario?
Thanks, Franco.Run the queries the cube is using in SSMS and turn on the Include Actual Execution Plan option.
https://msdn.microsoft.com/en-us/library/ms189562.aspx?f=255&MSPPError=-2147217396
Straight up it may suggest missing indexes which you can test to see if they improve the query performance. You can't take these suggestions as gospel - sometimes SQL Server gets it wrong - so you need to test them.
After that look in the query plan for any table scan operators. Unless you are actually retrieving every row in a table you shouldn't have any of these and they can probably be removed by placing a properly considered index on the table.
After that look for any RID Lookups or Key Lookups. These can generally be resolved fairly easily by adding the columns being looked up as "include" columns in the indexes.
Here are some links that might get you started.
Reading Execution Plans: http://www.mssqltips.com/sqlservertip/1873/how-to-read-sql-server-graphical-query-execution-plans/
Resolving Table Scans http://blog.sqlauthority.com/2007/03/30/sql-server-index-seek-vs-index-scan-table-scan/
Resolving Lookups: http://blog.sqlauthority.com/2009/11/09/sql-server-removing-key-lookup-seek-predicate-predicate-an-interesting-observation-related-to-datatypes/
Those are the obvious things - and generally the easiest to achieve. Performance tuning is a big area. It may be that the database queries are already performing perfectly well and the time being spent is processing the cube itself so you need
to establish where the time is going. There is no point trying to tune the database queries if they are already working well.
LucasF -
Tuning SQL query with SDO and Contains?
I'trying to optimize a query
with a sdo_filter and an intermedia_contains
on a 3.000.000 records table,
the query look like this
SELECT COUNT(*) FROM professionnel WHERE mdsys.sdo_filter(professionnel.coor_cart,mdsys.sdo_geometry(2003, null, null,mdsys.sdo_elem_info_array(1,1003,4),mdsys.sdo_ordinate_array(809990,2087279,778784,2087279,794387,2102882)),'querytype=window') = 'TRUE' AND professionnel.code_rubr ='12 3 30' AND CONTAINS(professionnel.Ctx,'PLOMBERIE within Nom and ( RUE within Adresse1 )',1)>0
and it takes 15s on a bi 750 pentium III with
1.5Go of memory running under 8.1.6 linux.
What can i do to improve this query time?
nullHi Vincent,
We have patches for Oracle 8.1.6 Spatial
on NT and Solaris.
These patches include bug fixes and
performance enhancements.
We are in the process of making these patches
avaialble in a permanent place, but until then, I will temporarily put the patches on:
ftp://oracle-ftp.oracle.com/
Log in as anonymous and use your email for
password.
The patches are in /tmp/outgoing in:
NT816-000706.zip - NT patch
libordsdo.tar - Solaris patch
I recommend doing some analysis on
individual pieces of the query.
i.e. time the following:
1)
SELECT COUNT(*)
FROM professionnel
WHERE mdsys.sdo_filter(
professionnel.coor_cart,
mdsys.sdo_geometry(
2003, null, null,
mdsys.sdo_elem_info_array(1,1003,4),
mdsys.sdo_ordinate_array(
809990,2087279,
778784,2087279,
794387,2102882)),
'querytype=window') = 'TRUE';
2)
SELECT COUNT(*)
FROM professionnel
WHERE CONTAINS(professionnel.Ctx,
'PLOMBERIE within Nom and ( RUE within Adresse1)',1) >0;
You might want to try reorganizing the entire
query as follows (no promises).
If you contact me directly, I can try to
help to further tune the SQL.
Hope this helps. Thanks.
Dan
select count(*)
FROM
(SELECT /*+ no_merge */ rowid
FROM professionnel
WHERE mdsys.sdo_filter(
professionnel.coor_cart,
mdsys.sdo_geometry(
2003, null, null,
mdsys.sdo_elem_info_array(1,1003,4),
mdsys.sdo_ordinate_array(809990,2087279,
778784,2087279,
794387,2102882)),
'querytype=window') = 'TRUE'
) a,
(SELECT /*+ no_merge */ rowid
FROM professionnel
WHERE CONTAINS(professionnel.Ctx,
'PLOMBERIE within Nom and
( RUE within Adresse1)',1) >0
) b
where a.rowid = b.rowid
and professionnel.code_rubr ='12 3 30';
**NOTE** Try this with no index on code_rubr
null -
Hi,
Can anyone assist me in tuning the below query
Thanks in Advance
A.Gopal
SELECT nvl(sum(p.GRP_ACTUALQUANTITY),0)
FROM GOODSRECEIPTS r, GOODSRECEIPTPOSITIONS p
,reportparameters plt,reportparameters spl,reportparameters mat
WHERE r.GRH_NO = p.GRP_GRH_NO
AND TRUNC(r.GRH_ARRIVAL) BETWEEN NVL(TO_DATE('01-jan-09'), TRUNC(r.GRH_ARRIVAL)) AND NVL(TO_DATE('31-jan-09'), TRUNC(r.GRH_ARRIVAL))
AND (p.GRP_PLT_ID = 'VDN' OR 1 =0)
AND (r.GRH_SPL_ID = '15035122' OR 1 =0)
AND (p.GRP_MAT_ID = '1001360' OR 1 =0)
AND ('01.01.2009' = 'TOTAL' or trunc(r.GRH_ARRIVAL,'mm') = to_date('01.01.2009','dd.mm.yyyy'))
and plt.rep_field = 'PLT_ID' AND plt.rep_id = 'AN_EXC_RAT' AND plt.rep_user = 'ANANTGOP'
and spl.rep_field = 'SPL_ID' AND spl.rep_id = 'AN_EXC_RAT' AND spl.rep_user ='ANANTGOP'
and mat.rep_field = 'MAT_ID' AND mat.rep_id = 'AN_EXC_RAT' AND mat.rep_user = 'ANANTGOP'
and r.GRH_SPL_ID = decode(spl.rep_value,'All',r.GRH_SPL_ID,spl.rep_value)
and p.GRp_plt_ID = decode(plt.rep_value,'All',p.GRp_plt_ID,plt.rep_value)
and p.GRp_mat_ID = decode(mat.rep_value,'All',p.GRp_mat_ID,mat.rep_value)
AND NOT EXISTS (SELECT 1 FROM GOODSRECEIPTUSAGESTATUS u
WHERE p.GRP_GRH_NO = u.GRU_GRP_GRH_NO
AND p.GRP_NO =u.GRU_GRP_NO
AND u.GRU_UST_ID = 'CANCEL')This query is used in my Oracle report. The original query is like beow
SELECT nvl(sum(p.GRP_ACTUALQUANTITY),0)
FROM GOODSRECEIPTS r, GOODSRECEIPTPOSITIONS p
,reportparameters plt,reportparameters spl,reportparameters mat
WHERE r.GRH_NO = p.GRP_GRH_NO
AND TRUNC(r.GRH_ARRIVAL) >= NVL(:l_date_from, TRUNC(r.GRH_ARRIVAL)) AND
TRUNC(r.GRH_ARRIVAL) <=NVL(:l_date_to, TRUNC(r.GRH_ARRIVAL))
AND (p.GRP_PLT_ID = :p_plt_id OR :ip_plt_group =0)
AND (r.GRH_SPL_ID = :p_spl_id OR :ip_spl_group =0)
AND (p.GRP_MAT_ID = :p_mat_id OR :ip_mat_group =0)
AND (:l_flag = 'TOTAL' or trunc(r.GRH_ARRIVAL,'mm') = to_date(:p_month_abc_sp,'dd.mm.yyyy'))
and plt.rep_field = 'PLT_ID' AND plt.rep_id = :ip_rep_id AND plt.rep_user = :ip_rep_user
and spl.rep_field = 'SPL_ID' AND spl.rep_id = :ip_rep_id AND spl.rep_user = :ip_rep_user
and mat.rep_field = 'MAT_ID' AND mat.rep_id = :ip_rep_id AND mat.rep_user = :ip_rep_user
and r.GRH_SPL_ID = decode(spl.rep_value,'All',r.GRH_SPL_ID,spl.rep_value)
and p.GRp_plt_ID = decode(plt.rep_value,'All',p.GRp_plt_ID,plt.rep_value)
and p.GRp_mat_ID = decode(mat.rep_value,'All',p.GRp_mat_ID,mat.rep_value)
AND NOT EXISTS (SELECT 1
FROM GOODSRECEIPTUSAGESTATUS u
WHERE p.GRP_GRH_NO = u.GRU_GRP_GRH_NO
AND p.GRP_NO =u.GRU_GRP_NO
AND u.GRU_UST_ID = 'CANCEL');
:ip_rep_id = 'AN_EXC_RAT'
:ip_rep_user = 'ANANTGOP
Value of :l_flag = '01.01.2009'
(:p_month_abc_sp = '01.01.2009'
Thanks
A.Gopal -
Simple Question on & in SQL query
I am executing the following query from the SQL*Plus (my data in the table contains P&G as the value of the column for name)
select * from emp where name = 'P&G'
This rightly prompts me for the value of &g
Please let me know any solution other than the following
1. set define off
2. set define <to some other charecter>
3. Execute the query in some third party tools other than sql*plusIs there a way we can do set define off from a
procedure - meaning I want something to perform the
same way as set define off inside a procedureDo you mean a stored procedure?
Stored procedures (and/or packages) do not have a problem with the ampersand character. That's only an issue when you are using SQL*Plus. -
Tuning (SQL Query has radically different Buffer GETS in each instance)
I have been noticing that on Node2 of my 10.2.0.3 RAC cluster CPU has been running 90% for the past couple of days and on Node1 we are at the normal 20-30%. I was comparing AWR for both instances and noticed that the same exact SQL was showing different GETS on each instance.
Both Instances are configured exactly the same. SGA 3GB, 2 dual core 1.5Ghz CPU on Solaris 10.
AWR For Node 1
SQL ordered by Gets
Resources reported for PL/SQL code includes the resources used by all SQL statements called by the code.
Total Buffer Gets: 8,199,224
Captured SQL account for 94.2% of Total
Buffer Gets Executions Gets per Exec %Total CPU Time (s) Elapsed Time (s) SQL Id SQL Module SQL Text
4,834,470 16,465 293.62 58.96 442.34 459.42 cs3w0nz7uanhc BEGIN HRW_EC_QUERY.CHECK_STUDE...
4,561,082 16,469 276.95 55.63 411.10 430.16 6vbpbvfburc4x SELECT COUNT(SECURE_PROGRAMS.P... AWR For Node 2
Buffer Gets Executions Gets per Exec %Total CPU Time (s) Elapsed Time (s) SQL Id SQL Module SQL Text
219,779,881 9,306 23,617.01 99.26 11791.62 32202.99 cs3w0nz7uanhc BEGIN HRW_EC_QUERY.CHECK_STUDE...
219,320,634 9,302 23,577.79 99.05 11760.22 32137.23 6vbpbvfburc4x SELECT COUNT(SECURE_PROGRAMS.P... Gets on Node 2 are about 45 times what they are on node 1. We are using bind variables in the SQL. The statements are completely identical. Anyone seen this before?
Thanks,
BrianAll parameters are the same between instances. Here is the result of the query.
PLAN_TABLE_OUTPUT
SQL_ID 6vbpbvfburc4x
SELECT COUNT(SECURE_PROGRAMS.PROG_ID) FROM SECURE_PROGRAMS,HRW_EC_ACTIVE_ITEM, (SELECT ACTIVE_ITEM_ID
FROM TABLE(CAST(:B1 AS HRW_EC_ACTIVE_ITEM_ID_TABLE_T)) ) T WHERE HRW_EC_ACTIVE_ITEM.ACTIVE_ITEM_ID =
T.ACTIVE_ITEM_ID AND HRW_EC_ACTIVE_ITEM.SPROG_ID = SECURE_PROGRAMS.PROG_ID AND
SECURE_PROGRAMS.STUDENT_RESOURCES_URL = :B2
Plan hash value: 25280318
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | | | 730 (100)| |
| 1 | SORT AGGREGATE | | 1 | 57 | | |
| 2 | HASH JOIN | | 116 | 6612 | 730 (1)| 00:00:09 |
| 3 | COLLECTION ITERATOR PICKLER FETCH| | | | | |
| 4 | NESTED LOOPS | | 48596 | 2610K| 705 (1)| 00:00:09 |
| 5 | INDEX RANGE SCAN | SECURE_PROGRAMS_IDX_04 | 4 | 76 | 2 (0)| 00:00:01 |
| 6 | INDEX RANGE SCAN | HRW_EC_ACTIVE_ITEM_IDX_03 | 10984 | 386K| 176 (1)| 00:00:03 |
Query Block Name / Object Alias (identified by operation id):
1 - SEL$62A3881B
5 - SEL$62A3881B / SECURE_PROGRAMS@SEL$1
6 - SEL$62A3881B / HRW_EC_ACTIVE_ITEM@SEL$1
SQL_ID 6vbpbvfburc4x
SELECT COUNT(SECURE_PROGRAMS.PROG_ID) FROM SECURE_PROGRAMS,HRW_EC_ACTIVE_ITEM, (SELECT ACTIVE_ITEM_ID
FROM TABLE(CAST(:B1 AS HRW_EC_ACTIVE_ITEM_ID_TABLE_T)) ) T WHERE HRW_EC_ACTIVE_ITEM.ACTIVE_ITEM_ID =
T.ACTIVE_ITEM_ID AND HRW_EC_ACTIVE_ITEM.SPROG_ID = SECURE_PROGRAMS.PROG_ID AND
SECURE_PROGRAMS.STUDENT_RESOURCES_URL = :B2
Plan hash value: 219484150
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | | | 4845 (100)| |
| 1 | SORT AGGREGATE | | 1 | 57 | | |
| 2 | HASH JOIN | | 2066 | 115K| 4845 (2)| 00:00:59 |
| 3 | INDEX RANGE SCAN | SECURE_PROGRAMS_IDX_04 | 79 | 1501 | 2 (0)| 00:00:01 |
| 4 | HASH JOIN | | 3284 | 121K| 4843 (2)| 00:00:59 |
| 5 | COLLECTION ITERATOR PICKLER FETCH| | | | | |
| 6 | INDEX FAST FULL SCAN | HRW_EC_ACTIVE_ITEM_IDX_03 | 1373K| 47M| 4803 (2)| 00:00:58 |
Query Block Name / Object Alias (identified by operation id):
1 - SEL$62A3881B
3 - SEL$62A3881B / SECURE_PROGRAMS@SEL$1
6 - SEL$62A3881B / HRW_EC_ACTIVE_ITEM@SEL$1
Note
- SQL profile "SYS_SQLPROF_014414387fd00001" used for this statement
SQL_ID 6vbpbvfburc4x
SELECT COUNT(SECURE_PROGRAMS.PROG_ID) FROM SECURE_PROGRAMS,HRW_EC_ACTIVE_ITEM, (SELECT ACTIVE_ITEM_ID
FROM TABLE(CAST(:B1 AS HRW_EC_ACTIVE_ITEM_ID_TABLE_T)) ) T WHERE HRW_EC_ACTIVE_ITEM.ACTIVE_ITEM_ID =
T.ACTIVE_ITEM_ID AND HRW_EC_ACTIVE_ITEM.SPROG_ID = SECURE_PROGRAMS.PROG_ID AND
SECURE_PROGRAMS.STUDENT_RESOURCES_URL = :B2
Plan hash value: 740005210
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | | | 4845 (100)| |
| 1 | SORT AGGREGATE | | 1 | 57 | | |
| 2 | HASH JOIN | | 7 | 399 | 4845 (2)| 00:00:59 |
| 3 | COLLECTION ITERATOR PICKLER FETCH| | | | | |
| 4 | HASH JOIN | | 2992 | 160K| 4821 (2)| 00:00:58 |
| 5 | INDEX RANGE SCAN | SECURE_PROGRAMS_IDX_04 | 33 | 627 | 2 (0)| 00:00:01 |
| 6 | INDEX FAST FULL SCAN | HRW_EC_ACTIVE_ITEM_IDX_03 | 1373K| 47M| 4803 (2)| 00:00:58 |
Query Block Name / Object Alias (identified by operation id):
1 - SEL$62A3881B
5 - SEL$62A3881B / SECURE_PROGRAMS@SEL$1
6 - SEL$62A3881B / HRW_EC_ACTIVE_ITEM@SEL$1
Note
- SQL profile "SYS_SQLPROF_014414387fd00001" used for this statement
SQL_ID 6vbpbvfburc4x
SELECT COUNT(SECURE_PROGRAMS.PROG_ID) FROM SECURE_PROGRAMS,HRW_EC_ACTIVE_ITEM, (SELECT ACTIVE_ITEM_ID
FROM TABLE(CAST(:B1 AS HRW_EC_ACTIVE_ITEM_ID_TABLE_T)) ) T WHERE HRW_EC_ACTIVE_ITEM.ACTIVE_ITEM_ID =
T.ACTIVE_ITEM_ID AND HRW_EC_ACTIVE_ITEM.SPROG_ID = SECURE_PROGRAMS.PROG_ID AND
SECURE_PROGRAMS.STUDENT_RESOURCES_URL = :B2
Plan hash value: 1418188916
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | | | 2136 (100)| |
| 1 | SORT AGGREGATE | | 1 | 57 | | |
| 2 | HASH JOIN | | 3 | 171 | 2136 (1)| 00:00:26 |
| 3 | NESTED LOOPS | | 1103 | 60665 | 2111 (1)| 00:00:26 |
| 4 | INDEX RANGE SCAN | SECURE_PROGRAMS_IDX_04 | 12 | 228 | 2 (0)| 00:00:01 |
| 5 | INDEX RANGE SCAN | HRW_EC_ACTIVE_ITEM_IDX_03 | 10984 | 386K| 176 (1)| 00:00:03 |
| 6 | COLLECTION ITERATOR PICKLER FETCH| | | | | |
Query Block Name / Object Alias (identified by operation id):
1 - SEL$62A3881B
4 - SEL$62A3881B / SECURE_PROGRAMS@SEL$1
5 - SEL$62A3881B / HRW_EC_ACTIVE_ITEM@SEL$1 Thanks,
Brian -
Tuning SQL query with similar subqueries for select columns
Hi all,
My query is something like below:
1> SELECT
2> A.COL1,
3> SUM(CASE WHEN A.flag=100 AND NVL(B.flag,0)=0 AND
4> EXISTS (
5> SELECT 'ROW_EXISTS'
6> FROM A A0
7> WHERE A0.COL2=100 AND NVL(A0.flag,0)=0 AND 0.DIRN<>A.DIRN)
8> THEN 1
9> ELSE 0
10> END) SUM_COLUMN1,
11>SUM(CASE WHEN A.flag=100 AND
12> EXISTS (
13> SELECT 'ROW_EXISTS'
14> FROM A A0
15> WHERE A0.COL2=100 AND A0.DIRN<>A.DIRN)
16> THEN 1
17> ELSE 0
18>END) SUM_COLUMN2
19>FROM A,B
20>WHERE A.COL=B.KEY_COL
21>GROUP BY A.COL1
My problem is that I need to index scan the tables A aliased as A0 in the two exist queries. Lines: 5-7 and 13-15.
The major performance degradation i see with the query is that it has to scan A0 twice to compute SUM_COLUMN1 and SUM_COLUMN2.
Is there any way by which i can use the same subquery to scan the table just once to compute the columns.
The table A has more than a 100million records. So i need to improve performance of this query though it is a small issue.
Please feel free to ask me more if i'm not clear with the example.
Thanks in advance,
RajAlso you could use analytic functions:
SQL> select deptno, sum(case when e.mgr is not null and
2 exists (select 1 from emp e1 where e1.empno <> e.empno
3 and e1.deptno = 10 and e1.sal >= 1500)
4 then 1 else 0 end) sum1,
5 sum(case when e.mgr is not null and e.sal >= 1200 and
6 exists (select 1 from emp e1 where e1.empno <> e.empno and e1.deptno = 10)
7 then 1 else 0 end) sum2
8 from emp e
9 group by deptno
10 /
DEPTNO SUM1 SUM2
10 2 2
20 5 3
30 6 5
SQL> select deptno, sum(case when mgr is not null and
2 (d12 != empno or empno !=d11) then 1 else 0 end) sum1,
3 sum(case when mgr is not null and (d21 != empno or empno !=d22)
4 and sal >= 1200 then 1 else 0 end) sum2
5 from (
6 select deptno, empno, mgr, sal,
7 min(case when deptno = 10 and sal >= 1500
8 then empno else -1 end) over(order by null) d11,
9 max(case when deptno = 10 and sal >= 1500
10 then empno else -1 end) over(order by null) d12,
11 min(case when deptno = 10 then empno else -1 end) over(order by null) d21,
12 max(case when deptno = 10 then empno else -1 end) over(order by null) d22
13 from emp e
14 )
15 group by deptno
16 /
DEPTNO SUM1 SUM2
10 2 2
20 5 3
30 6 5In your case it could be something like
SELECT COL1,
SUM( CASE WHEN a_flag = 100 and nvl(b_flag,0)=0 and
(DIRN != MIN_A OR DIRN != MAX_A) THEN 1 ELSE 0 END) SUM_COLUMN1,
SUM( CASE WHEN a_flag = 100 and
(DIRN != MIN_B OR DIRN != MAX_B) THEN 1 ELSE 0 END) SUM_COLUMN2
FROM (
SELECT A.COL1, A.FLAG A_FLAG, B.FLAG B_FLAG, A.DIRN,
MIN(CASE WHEN A.COL2=100 and NVL(A.flag,0) = 0 THEN A.DIRN ELSE null END) OVER(order by null) MIN_A,
MAX(CASE WHEN A.COL2=100 and NVL(A.flag,0) = 0 THEN A.DIRN ELSE null END) OVER(order by null) MAX_A,
MIN(CASE WHEN A.COL2=100 THEN A.DIRN ELSE null END) OVER(order by null) MIN_B,
MAX(CASE WHEN A.COL2=100 THEN A.DIRN ELSE null END) OVER(order by null) MAX_B
FROM A,B
WHERE A.COL=B.KEY_COL
GROUP BY COL1
Rgds. -
Tuning SQL Query for base tables
Hi,
Can any please help me to tune the below query...... there is full table scan for po_action_history table
SELECT DISTINCT
DECODE(hr.full_name,'Default Buyer, Purchasing','PCH',
'Default Buyer, Travel','TRV',
'Purchase Order, Rapid','RPO',
'Data Interchange, Electronic','EDI',fuser1.user_name) BUYER_ID,
poa.attribute1 BUYER_GROUP,
poa.attribute2 BUYER_SUBGROUP
FROM po.po_action_history ac1,
po.po_headers_all ph,
po.po_agents poa,
hr.per_all_people_f hr,
applsys.fnd_user fuser1
WHERE ph.po_header_id = ac1.object_id
AND ac1.object_type_code = 'PO'
AND ac1.action_code = 'APPROVE'
AND sequence_num =(SELECT MIN(ac2.sequence_num)
FROM po.po_action_history ac2,
applsys.fnd_user fuser2
WHERE ph.po_header_id = ac2.object_id
AND ac2.object_type_code = 'PO'
AND ac2.action_code = 'APPROVE'
AND ac2.last_updated_by = fuser2.user_id)
--AND ac1.last_updated_by = fuser1.user_id
AND ph.agent_id = poa.agent_id
AND ph.agent_id = hr.person_id
AND hr.person_id = fuser1.employee_id
AND hr.effective_end_date > sysdate
AND trunc(ac1.last_update_date) between '01-JAN-08' and '07-JAN-08'
ORDER BY poa.attribute1
Explain Plan
PLAN_TABLE_OUTPUT
Plan hash value: 3325319312
Id Operation Name Rows
Bytes Cost (%CPU) Time
PLAN_TABLE_OUTPUT
| 0 | SELECT STATEMENT | | 27 |
2754 | 38963 (3) | 00:07:48 |
| 1 | SORT UNIQUE | | 27 |
2754 | 38962 (3) | 00:07:48 |
|* 2 | FILTER | | |
| | |
|* 3 | HASH JOIN | | 37 |
3774 | 36308 (3) | 00:07:16 |
PLAN_TABLE_OUTPUT
| 4 | TABLE ACCESS BY INDEX ROWID | FND_USER | 1 |
13 | 2 (0) | 00:00:01 |
| 5 | NESTED LOOPS | | 37 |
3293 | 36303 (3) | 00:07:16 |
| 6 | NESTED LOOPS | | 88 |
6688 | 36180 (3) | 00:07:15 |
| 7 | NESTED LOOPS | | 88 |
PLAN_TABLE_OUTPUT
3960 | 35916 (3) | 00:07:11 |
|* 8 | TABLE ACCESS FULL | PO_ACTION_HISTORY | 2110 |
71740 | 32478 (3) | 00:06:30 |
| 9 | TABLE ACCESS BY INDEX ROWID | PO_HEADERS_ALL | 1 |
11 | 2 (0) | 00:00:01 |
|* 10 | INDEX UNIQUE SCAN | PO_HEADERS_U1 | 1 |
| 1 (0) | 00:00:01 |
PLAN_TABLE_OUTPUT
| 11 | SORT AGGREGATE | | 1 |
36 | | |
| 12 | NESTED LOOPS | | 1 |
36 | 6 (0) | 00:00:01 |
|* 13 | TABLE ACCESS BY INDEX ROWID| PO_ACTION_HISTORY | 1 |
31 | 6 (0) | 00:00:01 |
|* 14 | INDEX RANGE SCAN | PO_ACTION_HISTORY_N1 | 5 |
| 3 (0) | 00:00:01 |
PLAN_TABLE_OUTPUT
|* 15 | INDEX UNIQUE SCAN | FND_USER_U1 | 1 |
5 | 0 (0) | 00:00:01 |
| 16 | TABLE ACCESS BY INDEX ROWID | PER_ALL_PEOPLE_F | 1 |
31 | 3 (0) | 00:00:01 |
|* 17 | INDEX RANGE SCAN | PER_PEOPLE_F_PK | 1 |
| 2 (0) | 00:00:01 |
|* 18 | INDEX RANGE SCAN | FND_USER_N1 | 1 |
PLAN_TABLE_OUTPUT
| 1 (0) | 00:00:01 |
| 19 | TABLE ACCESS FULL | PO_AGENTS | 183 |
2379 | 4 (0) | 00:00:01 |
Predicate Information (identified by operation id):
PLAN_TABLE_OUTPUT
2 - filter(TO_DATE('01-JAN-08')<=TO_DATE('07-JAN-08'))
3 - access("PH"."AGENT_ID"="POA"."AGENT_ID")
8 - filter("AC1"."ACTION_CODE"='APPROVE' AND "AC1"."OBJECT_TYPE_CODE"='PO'AND
TRUNC(INTERNAL_FUNCTION("AC1"."LAST_UPDATE_DATE"))>='01-JAN-08' AND
TRUNC(INTERNAL_FUNCTION("AC1"."LAST_UPDATE_DATE"))<='07-JAN-08')
10 - access("PH"."PO_HEADER_ID"="AC1"."OBJECT_ID")
PLAN_TABLE_OUTPUT
filter("SEQUENCE_NUM"= (SELECT MIN("AC2"."SEQUENCE_NUM") FROM "APPLSYS"."FND_USER"
"FUSER2","PO"."PO_ACTION_HISTORY" "AC2" WHERE "AC2"."OBJECT_ID"=:B1 AND "AC2"."ACTION_CODE"='APPROVE'
AND "AC2"."OBJECT_TYPE_CODE"='PO' AND "AC2"."LAST_UPDATED_BY"="FUSER2"."USER_ID"))
13 - filter("AC2"."ACTION_CODE"='APPROVE' AND "AC2"."OBJECT_TYPE_CODE"='PO')
14 - access("AC2"."OBJECT_ID"=:B1)
PLAN_TABLE_OUTPUT
15 - access("AC2"."LAST_UPDATED_BY"="FUSER2"."USER_ID")
17 - access("PH"."AGENT_ID"="PERSON_ID" AND "EFFECTIVE_END_DATE">SYSDATE@!)
filter("EFFECTIVE_END_DATE">SYSDATE@!)
18 - access("PERSON_ID"="FUSER1"."EMPLOYEE_ID")
ThanksHi,
any help for the above issue. -
Consolidating multiple rows in 1 row, question with my SQL query
Hi, quick question.. I have a table with the following structure and data:
Table TEST
Usr id | Start Time | End Time | Dep_id |
123 | 8:00 | 10:00 | 1
123 | 10:00 | 12:00 | 1
548 | 12:00 | 14:00 | 2
549 | 10:00 | 12:00 | 3
549 |8:00 | 10:00 | 3
550 | 12:00 | 14:00 | 3
I need to consolidate start time and end time,
where the dep_id is the same,
and the usr Id is the same,
and start time = end Time.
The result will be something like:
Usr id | Start Time | End Time | Dep_id |
123 | 8:00 | 12:00 | 1
548 | 12:00 | 14:00 | 2
549 | 8:00 | 12:00 | 3
550 | 12:00 | 14:00 | 3
I'm doing something like:
SELECT MIN(START_TIME) START_TIME,
MAX(END_TIME) END_TIME,
DEP_ID
FROM TEST
GROUP BY DEP_ID;
This is consolidating, but I don't know how to add the conditions so it doesn't consolidate the last 3 rows in 1 (only 2 can be consolidated, the last row has a different usr_id)
anyone has a suggestion/solution?
thanks!This is not a full solution but may give you a way to complete
You may spit it to two SELECT with UNION ALL (based on gap you have)
WITH temp AS
(SELECT '123' user_id, 8 start_t, 10 end_t, 1 dept
FROM DUAL
UNION ALL
SELECT '123' user_id, 10 start_t, 12 end_t, 1 dept
FROM DUAL
UNION ALL
SELECT '548' user_id, 12 start_t, 14 end_t, 2 dept
FROM DUAL
UNION ALL
SELECT '549' user_id, 10 start_t, 12 end_t, 3 dept
FROM DUAL
UNION ALL
SELECT '549' user_id, 8 start_t, 10 end_t, 3 dept
FROM DUAL
UNION ALL
SELECT '550' user_id, 12 start_t, 14 end_t, 3 dept
FROM DUAL
UNION ALL
SELECT '549' user_id, 16 start_t, 18 end_t, 3 dept
FROM DUAL
SELECT du, start_t, end_t, next_st_t - end_t gap FROM (
SELECT dept||user_id du, start_t, end_t, LEAD (start_t)
OVER (PARTITION BY dept||user_id ORDER BY start_t) next_st_t from temp
DU START_T END_T GAP
1123 8 10 0
1123 10 12
2548 12 14
3549 8 10 0
3549 10 12 4
3549 16 18
3550 12 14 -
Question with PL - SQL Query.
I have following table named ProductStatus with values.....
ID.....Number.....Status.....Date
1..... 08-0001..... New..... 04/01/2008 05:04:00:000
2..... 08-0001..... New..... 04/01/2008 08:06:00:000
3..... 08-0001..... New..... 04/01/2008 09:01:00:000
4..... 08-0001..... Open..... 04/01/2008 10:12:00:000
5..... 08-0001..... Closed... 04/05/2008 10:12:00:000
6..... 08-0002..... New..... 04/02/2008 10:12:00:000
What i want is....
All the Rows(*) Where
1). Date < 02-APR-08 ( 04/02/2008 )
2). if there is similar Number then it should get only last status of that number (Means based on date it should get last status only)
Please Help me...
Thanks...
regards,
j@ySorry ...my Mistake here with column types...
Here it is corrected....
-- Create Table
CREATE TABLE ProductStatus
ID NUMBER(4,0),
Num VARCHAR2(20),
Status VARCHAR2(20),
StatusDate TIMESTAMP
-- Add Test Data
insert into ProductStatus(ID,Num,Status,StatusDate) Values (1,'08-0001','New',timestamp'2008-04-01 09:00:00.123456789');
insert into ProductStatus(ID,Num,Status,StatusDate) Values (2,'08-0001','New',timestamp'2008-04-01 05:04:00.123456789');
insert into ProductStatus(ID,Num,Status,StatusDate) Values (3,'08-0001','New',timestamp'2008-04-01 08:06:00.123456789');
insert into ProductStatus(ID,Num,Status,StatusDate) Values (4,'08-0001','Open',timestamp'2008-04-01 10:10:00.123456789');
insert into ProductStatus(ID,Num,Status,StatusDate) Values (5,'08-0002','New',timestamp'2008-04-05 10:12:00.123456789');
insert into ProductStatus(ID,Num,Status,StatusDate) Values (6,'08-0003','New',timestamp'2008-04-02 11:22:00.123456789');
Select All the Rows(*) Where
1). StatusDate < 02-APR-08 ( 04/02/2008 )
Select * from ProductStatus where StatusDate < to_date('02-Apr-08');
2). if there is similar Num then it should get only last status of that Num (Means based on date it should get last status only)
Confused with this..how to implement !!!!
Thanks,
regards,
j@y -
Hi All
Had a quick question about a SQL Query in a JSP - Can I duplicated an exact same record in a table with a new primary key without using the insert statement??
Say for example I have the following table:
OrderNo OrderName OrderType
======= ========== ========
1 Books Books
2 CDs CDs
3 DVDs DVDs
I want to make an exact copy of OrderNo 3 with new OrderNo 4, so that it will be something like:
4 DVDs DVDs
Any ideas friends??
LaterThanks Nikki, you are right. Actually it is my fault, I framed the question in a wrong way. Well, I found out the solution for that and here is the answer
insert into [tablename] (OrderNo) select 42506 from [sametablename] where OrderNo=42405 -
Need SQL Query which saves query results to an excel file
Hi,
I am looking for a sql query which saves/ export results of an query to a excel file
Thanks,
ChetanI am looking for a sql query which saves/ export results of an query to a excel file
Thanks,
Chetan
Options:
1) You can use
BCP command to export result to excel
2) Insert into excel by using OPENROWSET
3) Use Import and Export Wizard and provide SQL query as source and Excel as destination
Please refer:
http://stackoverflow.com/questions/87735/how-do-you-transfer-or-export-sql-server-2005-data-to-excel
http://www.codeproject.com/Questions/617527/Export-sql-query-result-in-excel-file
Cheers,
Vaibhav Chaudhari
[MCTS],
[MCP] -
Question about using objects in SQL query.
I had posted this question in the SQL/PLSQL forum but I guess nobody took the time to understand exactly what I am asking so I decided to try here hoping to get the answer. So here is the thing:
I have created generic object type "tree" - the constructor takes as a parameter sql query which returns "node_id" and "parent_node_id" - this is all we need to have a tree. The object has all related to a tree structure member functions and one of them is "oldest_relative" (the tree may not be fully connected - it may be more like a set of many trees, so it's not necessary all nodes to have the same root).
I also have departments table with the following fields: department_id, parent_department_id, department_name,...
all records in the table w/out parent_departments (parent_department_id is null) are considered divisions.
Now if I run the following query:
SELECT "DEPARTMENT_ID", "PARENT_DEPARTMENT_ID", "DEPARTMENT_NAME", tree('select department_id "node_id", parent_department_id "parent_node_id" from departments').oldest_relative("DEPARTMENT_ID") "DIVISION_ID" FROM departments
my question is: Is the tree object created for every row or does Oracle somehow caches the object since the object itself is not changing but only the parameter for the oldest_relative member function.
The table only has a few hunderd records and I can't see much of a difference in the execution time btw the query above and query like this:
SELECT "DEPARTMENT_ID", "PARENT_DEPARTMENT_ID", "DEPARTMENT_NAME", b.t.oldest_relative("DEPARTMENT_ID") "DIVISION_ID"
FROM departments left join (select tree('select department_id "node_id", parent_department_id "parent_node_id" from departments') t from dual) b on 1 = 1
where the object is clearly created just ones. (there is probably a better way to do it instead of this join)
Pls elaborate
GeorgeNot exactly sure what the question is...
As I understand, you are comparing the following two constructor calls:
+select.. tree('select department_id "node_id", parent_department_id "parent_node_id" from departments').oldest_relative("DEPARTMENT_ID") ... FROM ...+
+select tree('select department_id "node_id", parent_department_id "parent_node_id" from departments') ... FROM dual+
These calls are the same (besides the 1st one doing an immediate implicit call to a method of the object being constructed). The number of times these are being called depends on the number of times this SQL projection is applied - and that is determined by the number of rows being projected by the SELECT.
The latter one is against DUAL which only has a single row. So that constructor is only called once. The former can be against multiple rows. Obviously a single pass through a data set is desirable - which means that the sub-select (use by the constructor) should ideally only be executed once and makes the 2nd method more desirable.
However, I'm having a hard time understanding why the class and constructor are at all needed. Why pull data from a SQL table into PL memory? As that is where the class will need to cache and store the results of that construction parameter SQL SELECT. And once in PL memory, how does the object effectively access, search and use this cached data?
PL memory is expensive. It is not sharable.
PL data structures are primitive - these cannot be compared to SQL structures in the form of tables and columns that can be stored in a number of physical ways (index tables, hash tables, partitioned tables, clustered tables, etc). Cannot be indexed like SQL structures using B+tree, bitmap, function and other indexing methods. Cannot be sorted, grouped, analysed, filtered, etc like SQL structured data.
It makes very little sense to read SQL data into a class and then deal with that data, cached in expensive PL memory, using primitive PL structures.
And the same would be true if Java or C# was used. The best place for data is inside the SQL engine. That is the most superior environment for data. It can processes more data, scale better, perform better and offer more flexibility, than pulling data from it and then crunch that data using PL or Java or C#. -
How can i do SQl QUERY TUNING in Oracle 9i Database
Hello,
How can i do SQl QUERY TUNING in Oracle 9i Database You can start through reviewing the Performance Tuning Guide;
http://download.oracle.com/docs/cd/B10501_01/server.920/a96533/toc.htm
Good Luck!
Adith
Maybe you are looking for
-
Slight problem with threads....
Hello, Just started learning threads a few days ago.. my objective is to move an oval from left to right, then right to left, back and forth and so on.. however, it wont work, the source code i have below seems logical, but it doesnt fulfill my objec
-
Posted this in the iTunes forum as that's what I'm trying to restore using Time Machine, but thought I'd try here too Here's what happened.... Having a small hard drive on my old but current eMac and running out of room I decided to move my iTunes li
-
In previous versions, I would click the on the colour selection boxes (tool bar) and the colour difference would show in the Colour Picker box. The selected colour (new or current) would show. The target circle would physically move around. Now all
-
Satellite M40-145 - low DVD recording speed
My DVD-RW isn't burning over 2.4x speed. I tried with several DVD-R/+R brands, updated Matsu****a driver firmware, reinstalled recording software (Nero 6 and 7) but the problem mantains. What shoud I do?
-
Hi all, I have to implement a custom text component for a project im working on. I was hoping someone could give me some direction on how to implement the text storage. I wont need more than the regular 256 ascii characters and text sizes could reach