Reputation: 57
I need to optimize SELECT query in order to improve the performance. I am using ORACLE 10g. Below is my table:
CREATE TABLE TRNSCTN
(
TRNSCTN_ID VARCHAR2(32) NOT NULL,
TRNSCTN_DOC VARCHAR2(60) NOT NULL,
TRNSCTN_TYPE VARCHAR2(60) NOT NULL,
STATUS NUMBER NOT NULL,
TRNSCTN_CREATEDDATE DATE NOT NULL,
TRNSCTN_CREATEDBY VARCHAR2(60) NOT NULL,
TRNSCTN_CHANGEDDATE DATE NOT NULL,
TRNSCTN_CHANGEDBY VARCHAR2(60) NOT NULL,
PARENT_LINK VARCHAR2(32) NULL,
PT_NAME VARCHAR2(255) NULL,
APP_ID VARCHAR2(255) NULL,
DIRECTION NUMBER NULL,
CONSTRAINT PK_TRNSCTN_ID PRIMARY KEY (TRNSCTN_ID)
);
Below are some records:
Insert into TRNSCTN (TRNSCTN_ID,TRNSCTN_DOC,TRNSCTN_TYPE,STATUS,TRNSCTN_CREATEDDATE,TRNSCTN_CREATEDBY,TRNSCTN_CHANGEDDATE,TRNSCTN_CHANGEDBY,PARENT_LINK,PT_NAME,APP_ID,DIRECTION) values ('E840496554B91','DOC1','TYPE1',5501,to_date('01-MAY-13','DD-MON-RR'),'usr1',to_date('01-MAY-13','DD-MON-RR'),'usr1','E840496554B92','PT_SEMO','APP1',2 );
Insert into TRNSCTN (TRNSCTN_ID,TRNSCTN_DOC,TRNSCTN_TYPE,STATUS,TRNSCTN_CREATEDDATE,TRNSCTN_CREATEDBY,TRNSCTN_CHANGEDDATE,TRNSCTN_CHANGEDBY,PARENT_LINK,PT_NAME,APP_ID,DIRECTION) values ('E840496554B92','DOC2','TYPE1',5502,to_date('01-MAY-13','DD-MON-RR'),'usr1',to_date('01-MAY-13','DD-MON-RR'),'usr1','E840496554B92','PT_SEMO','APP1',1 );
Insert into TRNSCTN (TRNSCTN_ID,TRNSCTN_DOC,TRNSCTN_TYPE,STATUS,TRNSCTN_CREATEDDATE,TRNSCTN_CREATEDBY,TRNSCTN_CHANGEDDATE,TRNSCTN_CHANGEDBY,PARENT_LINK,PT_NAME,APP_ID,DIRECTION) values ('E840496554B93','DOC3','TYPE2',5503,to_date('01-MAY-13','DD-MON-RR'),'usr1',to_date('01-MAY-13','DD-MON-RR'),'usr1','E840496554B93','PT_SEMO','APP3',2 );
Insert into TRNSCTN (TRNSCTN_ID,TRNSCTN_DOC,TRNSCTN_TYPE,STATUS,TRNSCTN_CREATEDDATE,TRNSCTN_CREATEDBY,TRNSCTN_CHANGEDDATE,TRNSCTN_CHANGEDBY,PARENT_LINK,PT_NAME,APP_ID,DIRECTION) values ('E840496554B94','DOC1','TYPE2',5504,to_date('01-MAY-13','DD-MON-RR'),'usr1',to_date('01-MAY-13','DD-MON-RR'),'usr1','E840496554B91','PT_SEMO','APP1',2 );
Insert into TRNSCTN (TRNSCTN_ID,TRNSCTN_DOC,TRNSCTN_TYPE,STATUS,TRNSCTN_CREATEDDATE,TRNSCTN_CREATEDBY,TRNSCTN_CHANGEDDATE,TRNSCTN_CHANGEDBY,PARENT_LINK,PT_NAME,APP_ID,DIRECTION) values ('E840496554B95','DOC2','TYPE1',5505,to_date('01-MAY-13','DD-MON-RR'),'usr1',to_date('01-MAY-13','DD-MON-RR'),'usr1','E840496554B93','PT_SEMO','APP1',1 );
Insert into TRNSCTN (TRNSCTN_ID,TRNSCTN_DOC,TRNSCTN_TYPE,STATUS,TRNSCTN_CREATEDDATE,TRNSCTN_CREATEDBY,TRNSCTN_CHANGEDDATE,TRNSCTN_CHANGEDBY,PARENT_LINK,PT_NAME,APP_ID,DIRECTION) values ('E840496554B96','DOC1','TYPE1',5506,to_date('01-MAY-13','DD-MON-RR'),'usr1',to_date('01-MAY-13','DD-MON-RR'),'usr1','E840496554B92','PT_SEMO','APP3',2 );
Insert into TRNSCTN (TRNSCTN_ID,TRNSCTN_DOC,TRNSCTN_TYPE,STATUS,TRNSCTN_CREATEDDATE,TRNSCTN_CREATEDBY,TRNSCTN_CHANGEDDATE,TRNSCTN_CHANGEDBY,PARENT_LINK,PT_NAME,APP_ID,DIRECTION) values ('E840496554B97','DOC2','TYPE1',5507,to_date('01-MAY-13','DD-MON-RR'),'usr1',to_date('01-MAY-13','DD-MON-RR'),'usr1','E840496554B99','PT_SEMO','APP1',1 );
Insert into TRNSCTN (TRNSCTN_ID,TRNSCTN_DOC,TRNSCTN_TYPE,STATUS,TRNSCTN_CREATEDDATE,TRNSCTN_CREATEDBY,TRNSCTN_CHANGEDDATE,TRNSCTN_CHANGEDBY,PARENT_LINK,PT_NAME,APP_ID,DIRECTION) values ('E840496554B98','DOC3','TYPE2',5508,to_date('01-MAY-13','DD-MON-RR'),'usr1',to_date('01-MAY-13','DD-MON-RR'),'usr1','E840496554B93','PT_SEMO','APP1',1 );
Insert into TRNSCTN (TRNSCTN_ID,TRNSCTN_DOC,TRNSCTN_TYPE,STATUS,TRNSCTN_CREATEDDATE,TRNSCTN_CREATEDBY,TRNSCTN_CHANGEDDATE,TRNSCTN_CHANGEDBY,PARENT_LINK,PT_NAME,APP_ID,DIRECTION) values ('E840496554B99','DOC1','TYPE2',5509,to_date('01-MAY-13','DD-MON-RR'),'usr1',to_date('01-MAY-13','DD-MON-RR'),'usr1','E840496554B91','PT_SEMO','APP1',1 );
Insert into TRNSCTN (TRNSCTN_ID,TRNSCTN_DOC,TRNSCTN_TYPE,STATUS,TRNSCTN_CREATEDDATE,TRNSCTN_CREATEDBY,TRNSCTN_CHANGEDDATE,TRNSCTN_CHANGEDBY,PARENT_LINK,PT_NAME,APP_ID,DIRECTION) values ('E840496554B910','DOC2','TYPE1',5510,to_date('01-MAY-13','DD-MON-RR'),'usr1',to_date('01-MAY-13','DD-MON-RR'),'usr1','E840496554B93','PT_SEMO','APP3',1 );
Insert into TRNSCTN (TRNSCTN_ID,TRNSCTN_DOC,TRNSCTN_TYPE,STATUS,TRNSCTN_CREATEDDATE,TRNSCTN_CREATEDBY,TRNSCTN_CHANGEDDATE,TRNSCTN_CHANGEDBY,PARENT_LINK,PT_NAME,APP_ID,DIRECTION) values ('E840496554B911','DOC1','TYPE1',5511,to_date('01-MAY-13','DD-MON-RR'),'usr1',to_date('01-MAY-13','DD-MON-RR'),'usr1','E840496554B92','PT_SEMO','APP1',2 );
Insert into TRNSCTN (TRNSCTN_ID,TRNSCTN_DOC,TRNSCTN_TYPE,STATUS,TRNSCTN_CREATEDDATE,TRNSCTN_CREATEDBY,TRNSCTN_CHANGEDDATE,TRNSCTN_CHANGEDBY,PARENT_LINK,PT_NAME,APP_ID,DIRECTION) values ('E840496554B912','DOC2','TYPE1',5512,to_date('01-MAY-13','DD-MON-RR'),'usr1',to_date('01-MAY-13','DD-MON-RR'),'usr1','E840496554B913','PT_SEMO','APP1',1 );
Insert into TRNSCTN (TRNSCTN_ID,TRNSCTN_DOC,TRNSCTN_TYPE,STATUS,TRNSCTN_CREATEDDATE,TRNSCTN_CREATEDBY,TRNSCTN_CHANGEDDATE,TRNSCTN_CHANGEDBY,PARENT_LINK,PT_NAME,APP_ID,DIRECTION) values ('E840496554B913','DOC3','TYPE2',5513,to_date('01-MAY-13','DD-MON-RR'),'usr1',to_date('01-MAY-13','DD-MON-RR'),'usr1','E840496554B911','PT_SEMO','APP3',2 );
Now, here is my SELECT Query
SELECT TRNSCTN_ID,
TRNSCTN_DOC,
TRNSCTN_TYPE,
STATUS,
TRNSCTN_CREATEDDATE,
TRNSCTN_CREATEDBY,
TRNSCTN_CHANGEDDATE,
TRNSCTN_CHANGEDBY,
PARENT_LINK,
CASE
WHEN (SELECT COUNT(*) FROM TRNSCTN sub WHERE TRNSCTN_ID=sub.PARENT_LINK) = 0 THEN 'false'
ELSE 'true'
END AS CHILDCNT,
PT_NAME,
APP_ID,
DIRECTION
FROM TRNSCTN
As I am using the subquery to determine if the record has parent link, the query gets too much slower against millions of records.
Sorry that SQLFIDDLE is down so couldn't use it.
I was wondering, if there is another way to rewrite the query to optimize the performance.
Please let me know the optimized SELECT Query.
Thank you.
Upvotes: 0
Views: 2904
Reputation: 11
SELECT
TRNSCTN_ID,
TRNSCTN_DOC,
TRNSCTN_TYPE,
STATUS,
TRNSCTN_CREATEDDATE,
TRNSCTN_CREATEDBY,
TRNSCTN_CHANGEDDATE,
TRNSCTN_CHANGEDBY,
PARENT_LINK,
CHILDCNT,
PT_NAME,
APP_ID,
DIRECTION
FROM
(SELECT /*+use_hash(TRNSCTN, TRNSCTN1) */
TRNSCTN.TRNSCTN_ID,
TRNSCTN.TRNSCTN_DOC,
TRNSCTN.TRNSCTN_TYPE,
TRNSCTN.STATUS,
TRNSCTN.TRNSCTN_CREATEDDATE,
TRNSCTN.TRNSCTN_CREATEDBY,
TRNSCTN.TRNSCTN_CHANGEDDATE,
TRNSCTN.TRNSCTN_CHANGEDBY,
TRNSCTN.PARENT_LINK,
DECODE(COUNT(TRNSCTN1.TRNSCTN_ID) over (partition BY TRNSCTN.PARENT_LINK), 0, 'false', 'true') CHILDCNT,
TRNSCTN.PT_NAME,
TRNSCTN.APP_ID,
TRNSCTN.DIRECTION,
rank() over (partition BY TRNSCTN.TRNSCTN_ID order by TRNSCTN1.TRNSCTN_ID) r
FROM
TRNSCTN TRNSCTN,
TRNSCTN TRNSCTN1
WHERE
TRNSCTN.PARENT_LINK=TRNSCTN1.TRNSCTN_ID(+)
)
WHERE
r=1;
You can insert parallel hint if it nessesary
Upvotes: 0
Reputation: 167962
SELECT TRNSCTN_ID,
TRNSCTN_DOC,
TRNSCTN_TYPE,
STATUS,
TRNSCTN_CREATEDDATE,
TRNSCTN_CREATEDBY,
TRNSCTN_CHANGEDDATE,
TRNSCTN_CHANGEDBY,
PARENT_LINK,
CASE
WHEN NOT EXISTS (SELECT 1
FROM TRNSCTN sub
WHERE t.TRNSCTN_ID=sub.PARENT_LINK)
THEN 'false'
ELSE 'true'
END AS CHILDCNT,
PT_NAME,
APP_ID,
DIRECTION
FROM TRNSCTN t;
Upvotes: 1
Reputation: 103
Perhaps you could use a self join rather than a sub-query
i.e. puesdo-code:
SELECT <the_columns> FROM Transactions maintrans
LEFT OUTER JOIN (SELECT DISTINCT ParentID FROM Transactions) subtrans
ON maintrans.TranscationID = subtrans.ParentID
Now, where subtrans.ParentID is NULL, would equate to a transaction without a parent
Upvotes: 0
Reputation: 174
You can use left-join as i wrote below and you can consider giving parallel hint (e.g /*+ parallel */ )
SELECT sub.TRNSCTN_ID,
sub.TRNSCTN_DOC,
sub.TRNSCTN_TYPE,
sub.STATUS,
sub.TRNSCTN_CREATEDDATE,
sub.TRNSCTN_CREATEDBY,
sub.TRNSCTN_CHANGEDDATE,
sub.TRNSCTN_CHANGEDBY,
sub.PARENT_LINK,
DECODE(prnt.trnsctn_id, null, 'false', 'true') AS CHILDCNT,
sub.PT_NAME,
sub.APP_ID,
sub.DIRECTION
from TRNSCTN sub
left join TRNSCTN prnt
on sub.parent_link = prnt.trnsctn_id;
Upvotes: 4