【问题标题】:Oracle SQL SELECT subquery OptimizationOracle SQL SELECT 子查询优化
【发布时间】:2013-11-18 15:20:57
【问题描述】:

我需要优化 SELECT 查询以提高性能。我正在使用 ORACLE 10g。 下面是我的表:

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)
);

以下是一些记录:

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 );

现在,这是我的 SELECT 查询

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

当我使用子查询来确定记录是否有父链接时,查询对数百万条记录变得太慢了。

很抱歉,SQLFIDDLE 已关闭,因此无法使用它。

我想知道,是否有另一种方法来重写查询以优化性能。

请告诉我优化后的 SELECT Query。

谢谢。

【问题讨论】:

    标签: sql oracle select subquery query-optimization


    【解决方案1】:

    您可以使用我在下面写的左连接,您可以考虑提供并行提示(例如 /*+ 并行 */ )

        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;
    

    【讨论】:

      【解决方案2】:

      也许您可以使用自联接而不是子查询

      即puesdo代码:

      SELECT <the_columns> FROM Transactions maintrans
      LEFT OUTER JOIN (SELECT DISTINCT ParentID FROM Transactions) subtrans
      ON maintrans.TranscationID = subtrans.ParentID
      

      现在,如果 subtrans.ParentID 为 NULL,则相当于没有父级的事务

      【讨论】:

        【解决方案3】:
        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;
        

        SQLFIDDLE

        【讨论】:

          【解决方案4】:
          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;
          

          如果需要,您可以插入并行提示

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-02-23
            • 2023-01-12
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多