Oracle 11g:查询性能优化

时间:2017-10-06 08:32:06

标签: sql oracle database-performance

我对此特定查询存在性能问题:

lowers x

DDL

SELECT ID,
       NAME,
       CREATION_DATE,
       MODIFICATION_DATE,
       CREATION_USER,
       MODIFICATION_USER,
       CODE,
       START_DATE,
       TO_CHAR(ANSWER) AS ANSWER,
       STATUS,
       RESUME,
       REQUIRED,
       RTRIM(
         XMLAGG(
           XMLELEMENT(E,QW.WARD_ID,',').EXTRACT('//text()')
           ORDER BY QW.WARD_ID
         ).GetClobVal(),
         ','
       ) AS wards
FROM   RD_QUESTIONS Q
       LEFT JOIN RD_QUESTIONS_WARDS QW ON QW.QUESTION_ID = ID
GROUP BY ID,
       NAME,
       CREATION_DATE,
       MODIFICATION_DATE,
       CREATION_USER,
       MODIFICATION_USER,
       CODE,
       START_DATE,
       TO_CHAR(ANSWER),
       STATUS,
       RESUME,
       REQUIRED

问题在于CREATE TABLE RD_QUESTIONS( ID NUMBER(38, 0), NAME VARCHAR(255) NOT NULL, CREATION_DATE TIMESTAMP(6), MODIFICATION_DATE TIMESTAMP(6), CREATION_USER VARCHAR(20), MODIFICATION_USER VARCHAR(20), SECTION_ID NUMBER(38, 0), CHAPTER_ID NUMBER(38, 0), CONSTRAINT RD_QUESTIONS_PK3 PRIMARY KEY (ID), ); CREATE TABLE RD_QUESTIONS_WARDS( QUESTION_ID NUMBER(38, 0), WARD_ID NUMBER(38, 0), CONSTRAINT RD_QUESTIONS_WARDS_PK4 PRIMARY KEY (QUESTION_ID, WARD_ID), CONSTRAINT RD_QUESTIONS_FK4 FOREIGN KEY (QUESTION_ID) REFERENCES RD_QUESTIONS(ID) ); 语句 这计算起来真的很慢。

我正在寻找的结果是一个名为“wards”的列,所有匹配的id都连接到一个字符串。

任何拥有更好性能解决方案的人?

1 个答案:

答案 0 :(得分:3)

您可以将聚合移动到子查询中,这样就不需要按联接表的所有列进行分组:

SELECT Q.ID,
       Q.NAME,
       Q.CREATION_DATE,
       Q.MODIFICATION_DATE,
       Q.CREATION_USER,
       Q.MODIFICATION_USER,
       Q.CODE,
       Q.START_DATE,
       TO_CHAR(Q.ANSWER) AS ANSWER,
       Q.STATUS,
       Q.RESUME,
       Q.REQUIRED,
       QW.wards
FROM   RD_QUESTIONS Q
       LEFT JOIN (
         SELECT Question_ID,
                RTRIM(
                  XMLAGG(
                    XMLELEMENT(E,WARD_ID,',').EXTRACT('//text()')
                    ORDER BY WARD_ID
                 ).GetClobVal(),
                 ','
                ) AS wards
         FROM   RD_QUESTIONS_WARDS
         GROUP BY QUESTION_ID
       ) QW
       ON QW.QUESTION_ID = Q.ID

此外,如果汇总的WARD_ID字符串的长度永远不会超过4000个字符,则可以使用LISTAGG

FROM   RD_QUESTIONS Q
       LEFT JOIN (
         SELECT Question_ID,
                LISTAGG( WARD_ID, ',' ) WITHIN GROUP ( ORDER BY WARD_ID ) AS wards
         FROM   RD_QUESTIONS_WARDS
         GROUP BY QUESTION_ID
       ) QW
       ON QW.QUESTION_ID = Q.ID