Reputation: 2433
I have below query:
SELECT so1b.hasattachments,
so1b.sorefitem,
so1b.sonumber,
so1b.custponumber,
so1b.sodate,
so1b.ostatus,
so1b.osubstatus,
so1b.urefitem,
so1b.username,
so1b.summary,
so1b.purefitem
FROM (SELECT DECODE (COUNT (ATT.SOREFITEM), 0, 0, 1) hasattachments,
so1.SOREFITEM,
SONUMBER,
CUSTPONUMBER,
SODATE,
so1.OSTATUS,
so1.OSUBSTATUS,
so1.urefitem AS urefitem,
so1.username AS username ,
'' AS summary ,
so1.PUREFITEM
FROM ECOrders.SALESORDERS so1,
ECORDERS.ATTACHMENTS att,
ecusers.ownership o
WHERE att.SOREFITEM (+) =so1.SOREFITEM
AND so1.UREFITEM = o.urefitem
AND o.uownerref = ?
AND so1.sorefitem IN
(SELECT ot.sorefitem
FROM ECOrders.ORDERITEMS ot,
ECUSERS.USERINFO USI
WHERE ot.sorefitem=so1.sorefitem
AND OT.OSELLERID = USI.UREFITEM (+)
AND UPPER(USI.USERNAME) LIKE UPPER('%Dell Computer%') ESCAPE '~'
)
GROUP BY SO1.SOREFITEM,
SONUMBER,
CUSTPONUMBER,
SODATE,
so1.OSTATUS,
so1.OSUBSTATUS,
so1.UREFITEM,
so1.USERNAME,
so1.PUREFITEM
ORDER BY SOREFITEM DESC /* sort is possible on all columns */
) so1b
WHERE rownum BETWEEN 1 AND 10
This query performs very bad when data is large. Execution plan is as below:
ID PA_ID Execution Plan COST CARD BYTES
0 SELECT STATEMENT Optimizer=CHOOSE 2906 10 9480
1 0 -COUNT (STOPKEY)
2 1 --FILTER
3 2 ---VIEW 2906 381 361188
4 3 ----SORT (GROUP BY) 2906 381 32766
5 4 -----FILTER
6 5 ------NESTED LOOPS (OUTER) 18 2888 248368
7 6 -------NESTED LOOPS 17 2888 231040
8 7 --------TABLE ACCESS (BY INDEX ROWID) of 'ECUSERS.OWNERSHIP' (TABLE) 1 24 240
9 8 ---------INDEX (RANGE SCAN) of 'ECUSERS.OWNERSHIP_UOWNERREF' (INDEX) 1 24
10 7 --------TABLE ACCESS (BY INDEX ROWID) of 'ECORDERS.SALESORDERS' (TABLE) 1 121 8470
11 10 ---------INDEX (RANGE SCAN) of 'ECORDERS.SO_UREFITEM_OSTATUS_OSUB' (INDEX) 1 76
12 6 -------INDEX (RANGE SCAN) of 'ECORDERS.ATTACHMENTS_SOREFITEM' (INDEX) 1 1 6
13 5 ------NESTED LOOPS 2 1 49
14 13 -------TABLE ACCESS (BY INDEX ROWID) of 'ECORDERS.ORDERITEMS' (TABLE) 1 3 33
15 14 --------INDEX (RANGE SCAN) of 'ECORDERS.ORDERITEMS_SOREFITEM02' (INDEX) 1 3
16 13 -------INDEX (RANGE SCAN) of 'ECUSERS.USERINFO_I_USERNAME_UREFITEM' (INDEX (UNIQUE)) 1 1 38
ID PA_ID Execution Plan COST CARD BYTES
Is there any way I can improve performance of this query?
Upvotes: 3
Views: 125
Reputation:
I suggest replacing the in
clause with an exists
clause - like so:
AND exists
(SELECT null
FROM ECOrders.ORDERITEMS ot
JOIN ECUSERS.USERINFO USI
on OT.OSELLERID = USI.UREFITEM
AND UPPER(USI.USERNAME) LIKE UPPER('%Dell Computer%') ESCAPE '~'
WHERE ot.sorefitem=so1.sorefitem
)
The join between ORDERITEMS and USERINFO will be an inner join because you are only interested in items ordered by users from Dell Computer companies.
Upvotes: 1
Reputation: 23273
I would be looking to do the following:
WHERE
clause as this
will need to be executed one for every row in the table, not just
the 10 that you bring back./*+ FIRST_ROWS(10) */
hint to give the Oracle
optimizer a helping hand. Upvotes: 3