2017-10-06 170 views
2

我有性能問題與此特定的查詢:的Oracle 11g:查詢性能優化

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 

DDL

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

問題的發言RTRIM(XMLAGG(XMLELEMENT(E,WARD_ID,',').EXTRACT('//text()') ORDER BY WARD_ID).GetClobVal(),',') AS wards 那就是計算很慢。

我在找的結果是一個名爲「病房」的列,所有匹配的ID都加入到一個字符串中。

任何人都有更好的性能解決方案?

+0

請你能給的DDL兩個表,並編輯查詢,以顯示該表中的各列屬於因爲這將讓你選擇一個巨大的差異。即它是'Q.WARD_ID'還是'QW.WARD_ID'(對於其他列也是類似的) – MT0

回答

3

可以聚集移動到一個子查詢,所以你不必按連接表的所有列:如果累計的WARD_ID字符串的長度是永遠不會

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 

而且,要超過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 
+0

LISTAGG取得了訣竅,非常感謝。 – Pietro