Query performance [message #349565] |
Mon, 22 September 2008 04:27 |
ora_2007
Messages: 430 Registered: July 2007 Location: Mumbai
|
Senior Member |
|
|
Hi,
Following query takes 3 hours to complete.
Also it allocates 17g Temporary tablespace during execution.
MASTERL tablesize 25g
MARKETING tablesize 30g.
Please tell me what changes needed in the following query to become faster.
SELECT COUNT (A.ID) SEARCHED_MASTERLS
FROM CV_MASTERL A
WHERE 1 = 1
AND ( 1 = 1
AND (ID IN (
SELECT /*+ INDEX(B) */
A.ID
FROM MASTERL A, MARKETING B
WHERE (B.FF_ID = '1' OR B.FF_ID IS NULL)
AND A.ID = B.MASTERL_ID(+)
AND NVL (UPPER (B.VALUE), '¤') LIKE '%PARTNER%')
)
)
Table structure
CREATE TABLE MASTERL
(
ID NUMBER(12) NOT NULL primary key,
DATABASE_ID NUMBER(12) NOT NULL,
MASTERLNO VARCHAR2(15 BYTE),
FIRSTNAME VARCHAR2(255 BYTE)
)
CREATE INDEX MASTERL_DATABASE_FK_I ON MASTERL (DATABASE_ID)
CREATE TABLE MARKETING
(
DB_ID NUMBER(12) NOT NULL,
FF_ID NUMBER(12) NOT NULL,
MASTERL_ID NUMBER(12) NOT NULL,
VALUE VARCHAR2(255 BYTE)
)
CREATE INDEX MARKETING_DB_ID_IDX ON MARKETING (DB_ID)
CREATE INDEX MARKETING_IDX ON MARKETING (MASTERL_ID, DB_ID)
Operation OBJECT NAME ROWS Bytes COST OBJECT Node IN/OUT PStart PStop
-SELECT STATEMENT Optimizer MODE=ALL_ROWS 1 14 M
-SORT 1 58
-HASH JOIN RIGHT OUTER 124 K 6 M 14 M
INDEX FAST FULL SCAN CALC.CAMPAIGN_PK 20 K 99 K 15
-HASH JOIN SEMI 124 K 6 M 14 M
-TABLE ACCESS BY INDEX ROWID CALC.MASTERL 7 K 90 K 2167
-NESTED OOPS 527 K 20 M 31967
-NESTED LOOPS 69 1 K 22
-TABLE ACCESS BY INDEX ROWID CALC.USERS 1 15 2
INDEX RANGE SCAN CALC.USERS_DBUSERNAME_I 1 1
-TABLE ACCESS BY INDEX ROWID CALC.DATABASE 69 897 20
INDEX RANGE SCAN CALC.DATABASE_CLIENT_FK_I 43 1
INDEX RANGE SCAN CALC.MASTERL_DATABASE_FK_I 60 K 213
-VIEW SYS.VW_NSO_1 616 M 7G 14 M
-FILTER
-HASH JOIN OUTER 616 M 12G 14 M
INDEX FAST FULL SCAN CALC.MASTERLS_PK 222 M 1G 167570
-TABLE ACCESS BY INDEX ROWID CALC.MARKETING 600 M 7G 12 M
INDEX FULL SCAN CALC.FORMFETLVALUS_DB_ID_IDX 600 M 2067451
Thanks,
[Updated on: Mon, 22 September 2008 04:34] Report message to a moderator
|
|
|
Re: Query performance [message #349590 is a reply to message #349565] |
Mon, 22 September 2008 05:23 |
joshirish
Messages: 3 Registered: September 2008
|
Junior Member |
|
|
You may want to consider
1. Replacing the ID IN (A join B) with
CV_MASTERL INTERSECT MASTERL INTERSECT MARKETING
2. Replace the (B.FF_ID = '1' OR B.FF_ID IS NULL) with COALESCE/CASE
3. Try to discourage %SEARCHSTRING% queries (or use full text search indexes)
--Sjo
[Updated on: Mon, 22 September 2008 05:24] Report message to a moderator
|
|
|
Re: Query performance [message #349599 is a reply to message #349565] |
Mon, 22 September 2008 05:58 |
ora_2007
Messages: 430 Registered: July 2007 Location: Mumbai
|
Senior Member |
|
|
Thanks joshirish for your comments.
But it doesnt help in the current scenario.
Please tell me other solutions.
I think the problem is with the inner query.
But
SELECT A.ID
FROM MASTERL A, MARKETING B
WHERE (B.FF_ID = '1' OR B.FF_ID IS NULL)
AND A.ID = B.MASTERL_ID(+)
AND NVL (UPPER (B.VALUE), '¤') LIKE '%PARTNER%' ---This condition causes slowdown. How can this be improved?
Thanks,
|
|
|
Re: Query performance [message #349602 is a reply to message #349565] |
Mon, 22 September 2008 06:08 |
Kriptas
Messages: 118 Registered: June 2008
|
Senior Member |
|
|
try this select
SELECT COUNT (A.ID) SEARCHED_MASTERLS
FROM CV_MASTERL A
INNER JOIN MASTERL A1 on A.ID=A1.ID
LEFT JOIN MARKETING B ON A1.ID = B.MASTERL_ID
AND NVL (UPPER (B.VALUE), '¤') LIKE '%PARTNER%')
WHERE NVL(B.FF_ID,'1') = '1'
and show execution plan and time
|
|
|
Re: Query performance [message #349606 is a reply to message #349565] |
Mon, 22 September 2008 06:13 |
Kriptas
Messages: 118 Registered: June 2008
|
Senior Member |
|
|
and one more select regarding your last post
SELECT A.ID
FROM MASTERL A
LEFT JOIN (SELECT B.MASTERL_ID, B.FF_ID
FROM MARKETING B
WHERE NVL(B.FF_ID,'1') = '1'
AND UPPER (B.VALUE) LIKE '%PARTNER%') C ON C.MASTERL_ID=A.ID
WHERE NVL(C.FF_ID,'1') = '1'
there must be only HASH join, no nested loops
|
|
|
Re: Query performance [message #349661 is a reply to message #349599] |
Mon, 22 September 2008 09:56 |
JRowbottom
Messages: 5933 Registered: June 2006 Location: Sunny North Yorkshire, ho...
|
Senior Member |
|
|
In your query:SELECT A.ID
FROM MASTERL A, MARKETING B
WHERE (B.FF_ID = '1' OR B.FF_ID IS NULL)
AND A.ID = B.MASTERL_ID(+)
AND NVL (UPPER (B.VALUE), '¤') LIKE '%PARTNER%'
The Outer join serves only to restirct the optimizers set of options - you'll get all the Ids in table A - that's what an outer join does.
Your query is funtionally the same asSELECT COUNT (A.ID) SEARCHED_MASTERLS
FROM CV_MASTERL A
WHERE ID IN (SELECT B.ID
FROM MASTERL B)
|
|
|
Re: Query performance [message #349665 is a reply to message #349661] |
Mon, 22 September 2008 10:27 |
Kriptas
Messages: 118 Registered: June 2008
|
Senior Member |
|
|
JRowbottom wrote on Mon, 22 September 2008 09:56 | In your query:SELECT A.ID
FROM MASTERL A, MARKETING B
WHERE (B.FF_ID = '1' OR B.FF_ID IS NULL)
AND A.ID = B.MASTERL_ID(+)
AND NVL (UPPER (B.VALUE), '¤') LIKE '%PARTNER%'
The Outer join serves only to restirct the optimizers set of options - you'll get all the Ids in table A - that's what an outer join does.
Your query is funtionally the same asSELECT COUNT (A.ID) SEARCHED_MASTERLS
FROM CV_MASTERL A
WHERE ID IN (SELECT B.ID
FROM MASTERL B)
|
I do not agree
see predicate in where clause " (B.FF_ID = '1' OR B.FF_ID IS NULL)"
it shows that query gets from outer join rows where table A was joined with table B and B.FF_ID = '1' OR B.FF_ID IS NULL, AND table A was not joined with table B then B.FF_ID will be NULL and it fit to where clause predicate.
|
|
|
Re: Query performance [message #349799 is a reply to message #349665] |
Tue, 23 September 2008 03:02 |
JRowbottom
Messages: 5933 Registered: June 2006 Location: Sunny North Yorkshire, ho...
|
Senior Member |
|
|
The lines (B.FF_ID = '1' OR B.FF_ID IS NULL) is a poor mans version of the oracle outer join notation.
The Outer Join record returned if there is no match consists entirely of null values, so these clauses are just taking account of that possibility.
It is syntactically the same, but less clear than
|
|
|
Re: Query performance [message #349801 is a reply to message #349799] |
Tue, 23 September 2008 03:10 |
JRowbottom
Messages: 5933 Registered: June 2006 Location: Sunny North Yorkshire, ho...
|
Senior Member |
|
|
Looking at it again, there is a problem with the outer join in the original query. This lineAND NVL (UPPER (B.VALUE), '¤') LIKE '%PARTNER%' will completely undo the effects of the outer join, as null rows from table B will not be matched.
That would make the original query the same as this:SELECT COUNT (A.ID) SEARCHED_MASTERLS
FROM CV_MASTERL A
WHERE ID IN (SELECT A.ID
FROM MASTERL A, MARKETING B
WHERE B.FF_ID = '1'
AND A.ID = B.MASTERL_ID)
AND UPPER (B.VALUE) LIKE '%PARTNER%')
Rewrit that like this:SELECT COUNT (A.ID) SEARCHED_MASTERLS
FROM CV_MASTERL A
WHERE ID IN (SELECT A.ID
FROM MASTERL A, MARKETING B
WHERE B.FF_ID = '1'
AND A.ID = B.MASTERL_ID)
AND INSTR(B.VALUE,'PARTNER')>0
and create an index on Marketing(MASTERL_ID,FF_ID,INSTR(B.VALUE,'PARTNER') and you hould see some improvements.
|
|
|
Re: Query performance [message #349996 is a reply to message #349565] |
Tue, 23 September 2008 13:13 |
Kriptas
Messages: 118 Registered: June 2008
|
Senior Member |
|
|
maybe i do not understand you clearly, but I dissagree with you on:
The lines (B.FF_ID = '1' OR B.FF_ID IS NULL)is a poor mans version of the oracle outer join notation.
The Outer Join record returned if there is no match consists entirely of null values, so these clauses are just taking account of that possibility.
It is syntactically the same, but less clear thanB.FF_ID(+) = '1'
lest say, table B and table A was joined,
and B.FF_ID='2' (and other value then '1' and null), so in orginal query that rows will be filtered out, in yours query will be not.
i think that oracle convert character type '1' to 1 and join tables if there is match... but that will cost performance.
|
|
|