我有以下查询:
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
当数据很大时,此查询执行得非常糟糕。执行计划如下:
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
有什么方法可以提高此查询的效果吗?
答案 0 :(得分:3)
我希望做到以下几点:
WHERE
子句中对子查询的需要
将需要为表中的每一行执行一次,而不仅仅是
你带回来的那个。/*+ FIRST_ROWS(10) */
提示来提供Oracle
优化者伸出援助之手。 答案 1 :(得分:1)
我建议用in
子句替换exists
子句 - 如下所示:
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
)
ORDERITEMS和USERINFO之间的联接将是一个内部联接,因为您只对戴尔计算机公司的用户订购的项目感兴趣。