Queries op extended explain tabellen in DB2.

Met enige regelmaat brengt ABIS enkele artikelen over DB2 onder de titel Exploring DB2 .

In de Exploring DB2 van januari 2010 nodigde Peter Vanroose ons - de lezers - uit om een query in te sturen voor het presenteren van informatie uit de extended explain tabellen. Deze uitdaging heb ik natuurlijk graag aangenomen.

Dit document bevat de volgende onderdelen:


De Query

Voor de broodnodige variatie wilde ik een query maken met een Common Table Expression en ten minste één gepartitioneerde tabel. Een catalog query was daardoor minder geschikt. Dus heb ik een query gebouwd op de IVP database, want deze bevat een gepartitioneerde tabel. Bovendien hebben de meeste installaties de IVP database geïnstalleerd en hopelijk kan iedereen daardoor uit de voeten met onderstaande query.

Dat dit geen bijzonder efficiënte query is, behoeft geen betoog. Deze keer gaat het immers alleen om de explain data, niet om de performance van de query. Optimalisatie van deze query valt dan ook buiten de scope van dit artikel, evenals het aanmaken van de extended explain tabellen.
(Die staan overigens beschreven in de Performance Monitoring and Tuning Guide en worden aangemaakt door OSC. U kunt ook member DSNTIJOS uit de SDSNSAMP gebruiken.)


--
   with     managers
           (mgrno,
            mgrname
            )
   as      (select   distinct
                     mgr.empno
                   , strip(coalesce(firstnme, '')) CONCAT
                     ' ' CONCAT
                     strip(coalesce(lastname, '???')) as mgrname
            from     DSN8810.DEPT dept
            join     DSN8810.EMP  mgr
                 on  mgr.empno = dept.mgrno
            )
   select   mgr.mgrname
          , dept.deptname
          , emp.lastname
          , emp.firstnme
   from     DSN8810.EMP emp
   left outer join
            DSN8810.DEPT dept
        on  dept.deptno = emp.workdept
   left outer join
            managers mgr
        on  mgr.mgrno = dept.mgrno
   where    emp.empno between '000000' and '150000'
        and emp.workdept between 'A' and 'EEE'
   order by case when dept.deptno IS NULL
                 then '*No dept'
                 when mgr.mgrno IS NULL
                 then '*No mgr'
                 else mgr.mgrname
            end,
            emp.empno
  ;

---------+---------+---------+---------+---------+---------+---------+---------+---------+---------
MGRNAME                       DEPTNAME                              LASTNAME         FIRSTNME
---------+---------+---------+---------+---------+---------+---------+---------+---------+---------
CHRISTINE HAAS                SPIFFY COMPUTER SERVICE DIV.          HAAS             CHRISTINE
CHRISTINE HAAS                SPIFFY COMPUTER SERVICE DIV.          LUCCHESI         VINCENZO
CHRISTINE HAAS                SPIFFY COMPUTER SERVICE DIV.          O'CONNELL        SEAN
EVA PULASKI                   ADMINISTRATION SYSTEMS                PULASKI          EVA
EVA PULASKI                   ADMINISTRATION SYSTEMS                JEFFERSON        JAMES
EVA PULASKI                   ADMINISTRATION SYSTEMS                MARINO           SALVATORE
EVA PULASKI                   ADMINISTRATION SYSTEMS                SMITH            DANIEL
EVA PULASKI                   ADMINISTRATION SYSTEMS                JOHNSON          SYBIL
EVA PULASKI                   ADMINISTRATION SYSTEMS                PEREZ            MARIA
IRVING STERN                  MANUFACTURING SYSTEMS                 STERN            IRVING
IRVING STERN                  MANUFACTURING SYSTEMS                 ADAMSON          BRUCE
IRVING STERN                  MANUFACTURING SYSTEMS                 PIANKA           ELIZABETH
IRVING STERN                  MANUFACTURING SYSTEMS                 YOSHIMURA        MASATOSHI
IRVING STERN                  MANUFACTURING SYSTEMS                 SCOUTTEN         MARILYN
IRVING STERN                  MANUFACTURING SYSTEMS                 WALKER           JAMES
IRVING STERN                  MANUFACTURING SYSTEMS                 BROWN            DAVID
IRVING STERN                  MANUFACTURING SYSTEMS                 JONES            WILLIAM
IRVING STERN                  MANUFACTURING SYSTEMS                 LUTZ             JENNIFER
MICHAEL THOMPSON              PLANNING                              THOMPSON         MICHAEL
SALLY KWAN                    INFORMATION CENTER                    KWAN             SALLY
SALLY KWAN                    INFORMATION CENTER                    QUINTANA         DOLORES
SALLY KWAN                    INFORMATION CENTER                    NICHOLLS         HEATHER
DSNE610I NUMBER OF ROWS DISPLAYED IS 22
DSNE616I STATEMENT EXECUTION WAS SUCCESSFUL, SQLCODE IS 100

Explain met Range informatie

Na uitvoering van

   EXPLAIN ALL SET QUERYNO=114 FOR

met bovenstaande query hebben we de diverse explain tabellen voorzien van data.

Een basis-query op alleen de PLAN_TABLE levert het inzicht op, dat er 7 stappen (tabelregels) zijn voor het uitvoeren van deze query. Uit de DSN_SORT_TABLE leren we dat er 4 sort-stappen zijn: twee voor de order-by clause, 1 voor de distinct clause in de Common Table Expression, en 1 voor het uitvoeren van de join met de resultaat-set van de CTE.

Als eerste stap wilde ik mijn standaard-query voor PLAN_TABLE uitbreiden met gegevens voor een eventuele page-range scan. Dat maakt immers een tablespace scan (accesstype=R) iets minder bezwaarlijk... Hiertoe dienen we de betreffende info uit de tabel DSN_PGRANGE_TABLE te gebruiken. Ik heb er voor gekozen om het aantal deelnemende partities toe te voegen aan de access kolom.

Bij onderstaande query en resultaten vallen de volgende zaken op:

De query en bijbehorende resultaten zien er als volgt uit:


--
-- Query on PLAN_TABLE with Page-Range info
--
   SELECT   SUBSTR(STRIP(CHAR(PLAN.QUERYNO)), 1, 5) AS QUERY
          , CASE PLAN.PARENT_QBLOCKNO
                 WHEN 0 THEN ' '
                        ELSE
                        SUBSTR(STRIP(CHAR(PLAN.PARENT_QBLOCKNO)), 1, 4)
            END AS PBLK
          , SUBSTR(STRIP(CHAR(PLAN.QBLOCKNO)), 1, 4) AS QBLK
          , SUBSTR(STRIP(CHAR(PLAN.PLANNO)), 1, 4) AS PLNO
          , CASE PLAN.MIXOPSEQ
                 WHEN 0 THEN ' '
                        ELSE SUBSTR(STRIP(CHAR(PLAN.MIXOPSEQ)), 1, 4)
            END AS OPSQ
          , PLAN.QBLOCK_TYPE AS TYPE
          , CASE PLAN.JOIN_TYPE
                 WHEN 'F' THEN 'Full'
                 WHEN 'P' THEN 'Pair'
                 WHEN 'S' THEN 'Star'
                 WHEN 'L' THEN CASE PLAN.METHOD
                                    WHEN 1 THEN 'L/R'
                                    WHEN 2 THEN 'L/R'
                                    WHEN 4 THEN 'L/R'
                                           ELSE '?'
                                    END
                 WHEN ' ' THEN CASE PLAN.METHOD
                                    WHEN 1 THEN 'Innr'
                                    WHEN 2 THEN 'Innr'
                                    WHEN 4 THEN 'Innr'
                                           ELSE ' '
                                    END
                          ELSE '*ERR*'
            END AS JOIN
          , CASE PLAN.METHOD
                 WHEN 0 THEN 'First'
                 WHEN 1 THEN 'NLjoin'
                 WHEN 2 THEN 'MSjoin'
                 WHEN 3 THEN 'Sort'
                 WHEN 4 THEN 'Hybrid'
                        ELSE 'UNKNWN'
            END AS METHOD
          , CASE PLAN.TABLE_TYPE
                 WHEN 'B' THEN 'Buffer'
                 WHEN 'C' THEN 'CTE'
                 WHEN 'F' THEN 'TabFun'
                 WHEN 'M' THEN 'MQT'
                 WHEN 'Q' THEN 'Temp'
                 WHEN 'R' THEN 'Recurs'
                 WHEN 'T' THEN 'Table'
                 WHEN 'W' THEN 'Work'
                          ELSE ' '
            END AS TYPE
          , SUBSTR(PLAN.CREATOR, 1, 8) AS CREATOR
          , SUBSTR(PLAN.TNAME, 1, 18) AS TABLE
          , SUBSTR(PLAN.ACCESSNAME, 1, 8) AS NDXNAME
          , CASE PLAN.PRIMARY_ACCESSTYPE
                 WHEN 'D' THEN 'D/'
                 WHEN 'T' THEN 'T/'
                          ELSE ''
            END CONCAT
            STRIP(PLAN.ACCESSTYPE) CONCAT
            CASE WHEN PLAN.PAGE_RANGE = 'Y'
                 THEN '(' CONCAT
                      STRIP(SUBSTR(STRIP(CHAR(RANGE.NUMPARTS)), 1, 4))
                      CONCAT ')'
                 ELSE ''
            END AS ACCESS
          , CASE PLAN.PREFETCH
                 WHEN 'S' THEN 'SEQ'
                 WHEN 'L' THEN 'LST'
                 WHEN 'D' THEN 'DYN'
                          ELSE ' '
            END AS PREF
          , CASE PLAN.INDEXONLY
                 WHEN 'Y' THEN 'XO'
                          ELSE ' '
            END AS XO
          , CASE PLAN.MATCHCOLS
                 WHEN 0 THEN ''
                        ELSE SUBSTR(STRIP(CHAR(PLAN.MATCHCOLS)), 1, 2)
            END AS MC
          , CASE PLAN.SORTC_GROUPBY
                 WHEN 'Y' THEN 'G'
                          ELSE ' '
            END CONCAT
            CASE PLAN.SORTC_JOIN
                 WHEN 'Y' THEN 'J'
                          ELSE ' '
            END CONCAT
            CASE PLAN.SORTC_ORDERBY
                 WHEN 'Y' THEN 'O'
                          ELSE ' '
            END CONCAT
            CASE PLAN.SORTC_UNIQ
                 WHEN 'Y' THEN 'U'
                          ELSE ' '
            END CONCAT
            CASE PLAN.SORTN_GROUPBY
                 WHEN 'Y' THEN 'G'
                          ELSE ' '
            END CONCAT
            CASE PLAN.SORTN_JOIN
                 WHEN 'Y' THEN 'J'
                          ELSE ' '
            END CONCAT
            CASE PLAN.SORTN_ORDERBY
                 WHEN 'Y' THEN 'O'
                          ELSE ' '
            END CONCAT
            CASE PLAN.SORTN_UNIQ
                 WHEN 'Y' THEN 'U'
                          ELSE ' '
            END AS GJOUGJOU
          , CASE PLAN.PARALLELISM_MODE
                 WHEN 'I' THEN 'I/O'
                 WHEN 'C' THEN 'CPU'
                 WHEN 'X' THEN 'SYS'
                          ELSE ' '
            END AS PAR
          , CASE PLAN.CTEREF
                 WHEN 0 THEN ' '
                 ELSE STRIP(CHAR(PLAN.CTEREF))
            END AS CTEREF
   FROM     PLAN_TABLE PLAN
   LEFT OUTER JOIN
            DSN_PGRANGE_TABLE RANGE
        ON  RANGE.QUERYNO  = PLAN.QUERYNO
        AND RANGE.QBLOCKNO = PLAN.QBLOCKNO
        AND RANGE.TABNO    = PLAN.TABNO
   WHERE    PLAN.QUERYNO = 114
   ORDER BY PLAN.QUERYNO
          , PLAN.PARENT_QBLOCKNO DESC
          , PLAN.QBLOCKNO
          , PLAN.PLANNO
          , PLAN.MIXOPSEQ
  ;

---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------
QUERY  PBLK  QBLK  PLNO  OPSQ  TYPE    JOIN   METHOD  TYPE    CREATOR   TABLE               NDXNAME   ACCESS      PREF  XO  MC  GJOUGJOU  PAR  CTEREF
---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------
114    1     3     1           TABLEX         First   Table   DSN8810   DEPT                XDEPT2    I                 XO
114    1     3     2           TABLEX  Innr   NLjoin  Table   DSN8810   EMP                 XEMP1     I                     1
114    1     3     3           TABLEX         Sort                                                                                 U
114          1     1           SELECT         First   Table   DSN8810   EMP                 XEMP2     I(2)        LST       1
114          1     2           SELECT  L/R    NLjoin  Table   DSN8810   DEPT                XDEPT1    I                     1
114          1     3           SELECT  L/R    NLjoin  Work    TU00001   MANAGERS                      T/R                            J
114          1     4           SELECT         Sort                                                                                O
DSNE610I NUMBER OF ROWS DISPLAYED IS 7
DSNE616I STATEMENT EXECUTION WAS SUCCESSFUL, SQLCODE IS 100

Explain met Range en Sort informatie

Vervolgens wilde ik zien, of ik ook de informatie uit DSN_SORT_TABLE in deze query kon opnemen om zo een beter totaal-beeld van de query te verkrijgen. Complicatie hierbij is, dat dit aanvullende rijen uit een andere tabel betreft, en dat er dus een UNION ALL moet worden toegepast. Op zich geen punt, maar het heeft wel enkele consequenties:

Allereerst dient de ORDER BY clausule aangepast te worden. Deze kan niet langer met kolom-namen werken, maar moet nu worden geformuleerd met gebruikmaking van kolom-nummers. Dat maakt de query minder leesbaar en begrijpelijk, maar het is niet anders.

Tevens ontstaat nu de situatie dat beide sub-queries een WHERE-clausule bevatten waarin de juiste query moet worden geselecteerd voor het ophalen van de explain data. Ik houd daar niet van; enerzijds omdat het redundant is, en anderzijds omdat het te vaak gebeurt dat de where clausules uit de pas gaan lopen, waardoor het eindresultaat niet meer bruikbaar is. Daarom heb ik de CTE QUERIES toegevoegd om het nummer (of de nummers) van de te explainen query/queries te definiëren.

Verder bleek ik nog twee extra CTEs nodig te hebben om de te sorteren tabel-nummers en de bijbehorende tabel-namen te vinden.
Om de resultaten van deze CTEs in omvang te beperken, heb ik opnieuw gebruik gemaakt van de CTE QUERIES die de relevante query-nummers bevat. Zodoende vervangt de CTE QUERIES nu in totaal 4 WHERE clausules.

Aldus heb ik drie CTEs aan mijn query toegevoegd om mijn query verder mee uit te bouwen. Dit hield echter een risico in: bij gebruik van drie of meer CTEs kan een CONCAT functie in de resultaat-set resulteren in kolom-waarden die een extra voorloop-byte krijgen met waarde X'00', wat erg storend kan zijn.
In deze query komt dat gelukkig niet voor. Dat komt omdat niet voldaan is aan de "eis" voor het optreden van dit probleem dat er tussen de CTEs een specifieke relatie moet bestaan.

Nadat ik dat had geverifieerd kon ik de query daadwerkelijk verder uitwerken. Het eerste deel van de query bleef vrijwel ongewijzigd. Eigenlijk hoefde alleen de Where-clausule aangepast te worden. De selectie op query-nummer moest worden vervangen door een inner join met de relevante query-nummers (CTE queries). Maar omdat de SORT-gegevens nu uit een andere tabel gehaald gaan worden, kunnen de rijen met METHOD=3 worden overgeslagen.

Voor het toevoegen van de sorteer-gegevens is een tweede query aan de eerste toegevoegd. Deze levert natuurlijk een resultaat-set met dezelfde kolommen, maar haalt haar informatie uit DSN_SORT_TABLE in plaats van PLAN_TABLE.

Ook bij deze query zijn enkele kanttekeningen te plaatsen:

Deze query en bijbehorende resultaten zien er als volgt uit:


--
-- Query on PLAN_TABLE with Page-Range info
--                      and sorting info
--
   WITH     QUERIES
           (QUERYNO)
   AS      (SELECT   114
            FROM     SYSIBM.SYSDUMMY1
            )
          , SORTKEYS
   AS      (SELECT DISTINCT
                     SKEY.QUERYNO
                   , SKEY.QBLOCKNO
                   , SKEY.PLANNO
                   , SKEY.SORTNO
                   , SKEY.TABNO
            FROM     DSN_SORTKEY_TABLE SKEY
            JOIN     QUERIES QRYS
                 ON  QRYS.QUERYNO = SKEY.QUERYNO
            WHERE    SKEY.TABNO <> 0
            )
          , TABLES
   AS      (SELECT DISTINCT
                     PLAN.QUERYNO
                   , PLAN.TABNO
                   , PLAN.TABLE_TYPE
                   , PLAN.CREATOR
                   , PLAN.TNAME
            FROM     PLAN_TABLE PLAN
            JOIN     QUERIES QRYS
                 ON  QRYS.QUERYNO = PLAN.QUERYNO
            WHERE    PLAN.TABNO <> 0
            )
   SELECT   SUBSTR(STRIP(CHAR(PLAN.QUERYNO)), 1, 5) AS QUERY
          , CASE PLAN.PARENT_QBLOCKNO
                 WHEN 0 THEN ' '
                        ELSE
                        SUBSTR(STRIP(CHAR(PLAN.PARENT_QBLOCKNO)), 1, 4)
            END AS PBLK
          , SUBSTR(STRIP(CHAR(PLAN.QBLOCKNO)), 1, 4) AS QBLK
          , SUBSTR(STRIP(CHAR(PLAN.PLANNO)), 1, 4) AS PLNO
          , CASE PLAN.MIXOPSEQ
                 WHEN 0 THEN ' '
                        ELSE SUBSTR(STRIP(CHAR(PLAN.MIXOPSEQ)), 1, 4)
            END AS OPSQ
          , PLAN.QBLOCK_TYPE AS TYPE
          , CASE PLAN.JOIN_TYPE
                 WHEN 'F' THEN 'Full'
                 WHEN 'P' THEN 'Pair'
                 WHEN 'S' THEN 'Star'
                 WHEN 'L' THEN CASE PLAN.METHOD
                                    WHEN 1 THEN 'L/R'
                                    WHEN 2 THEN 'L/R'
                                    WHEN 4 THEN 'L/R'
                                           ELSE '?'
                                    END
                 WHEN ' ' THEN CASE PLAN.METHOD
                                    WHEN 1 THEN 'Innr'
                                    WHEN 2 THEN 'Innr'
                                    WHEN 4 THEN 'Innr'
                                           ELSE ' '
                                    END
                          ELSE '*ERR*'
            END AS JOIN
          , CASE PLAN.METHOD
                 WHEN 0 THEN 'First'
                 WHEN 1 THEN 'NLjoin'
                 WHEN 2 THEN 'MSjoin'
                 WHEN 3 THEN 'Sort'
                 WHEN 4 THEN 'Hybrid'
                        ELSE 'UNKNWN'
            END AS METHOD
          , CASE PLAN.TABLE_TYPE
                 WHEN 'B' THEN 'Buffer'
                 WHEN 'C' THEN 'CTE'
                 WHEN 'F' THEN 'TabFun'
                 WHEN 'M' THEN 'MQT'
                 WHEN 'Q' THEN 'Temp'
                 WHEN 'R' THEN 'Recurs'
                 WHEN 'T' THEN 'Table'
                 WHEN 'W' THEN 'Work'
                          ELSE ' '
            END AS TYPE
          , SUBSTR(PLAN.CREATOR, 1, 8) AS CREATOR
          , SUBSTR(PLAN.TNAME, 1, 18) AS TABLE
          , SUBSTR(PLAN.ACCESSNAME, 1, 8) AS NDXNAME
          , CASE PLAN.PRIMARY_ACCESSTYPE
                 WHEN 'D' THEN 'D/'
                 WHEN 'T' THEN 'T/'
                          ELSE ''
            END CONCAT
            STRIP(PLAN.ACCESSTYPE) CONCAT
            CASE WHEN PLAN.PAGE_RANGE = 'Y'
                 THEN '(' CONCAT
                      STRIP(SUBSTR(STRIP(CHAR(RANGE.NUMPARTS)), 1, 4))
                      CONCAT ')'
                 ELSE ''
            END AS ACCESS
          , CASE PLAN.PREFETCH
                 WHEN 'S' THEN 'SEQ'
                 WHEN 'L' THEN 'LST'
                 WHEN 'D' THEN 'DYN'
                          ELSE ' '
            END AS PREF
          , CASE PLAN.INDEXONLY
                 WHEN 'Y' THEN 'XO'
                          ELSE ' '
            END AS XO
          , CASE PLAN.MATCHCOLS
                 WHEN 0 THEN ''
                        ELSE SUBSTR(STRIP(CHAR(PLAN.MATCHCOLS)), 1, 2)
            END AS MC
          , CASE PLAN.SORTC_GROUPBY
                 WHEN 'Y' THEN 'G'
                          ELSE ' '
            END CONCAT
            CASE PLAN.SORTC_JOIN
                 WHEN 'Y' THEN 'J'
                          ELSE ' '
            END CONCAT
            CASE PLAN.SORTC_ORDERBY
                 WHEN 'Y' THEN 'O'
                          ELSE ' '
            END CONCAT
            CASE PLAN.SORTC_UNIQ
                 WHEN 'Y' THEN 'U'
                          ELSE ' '
            END CONCAT
            CASE PLAN.SORTN_GROUPBY
                 WHEN 'Y' THEN 'G'
                          ELSE ' '
            END CONCAT
            CASE PLAN.SORTN_JOIN
                 WHEN 'Y' THEN 'J'
                          ELSE ' '
            END CONCAT
            CASE PLAN.SORTN_ORDERBY
                 WHEN 'Y' THEN 'O'
                          ELSE ' '
            END CONCAT
            CASE PLAN.SORTN_UNIQ
                 WHEN 'Y' THEN 'U'
                          ELSE ' '
            END AS GJOUGJOU
   FROM     PLAN_TABLE PLAN
   JOIN     QUERIES QRYS
        ON  QRYS.QUERYNO = PLAN.QUERYNO
   LEFT OUTER JOIN
            DSN_PGRANGE_TABLE RANGE
        ON  RANGE.QUERYNO  = PLAN.QUERYNO
        AND RANGE.QBLOCKNO = PLAN.QBLOCKNO
        AND RANGE.TABNO    = PLAN.TABNO
   WHERE    PLAN.METHOD <> 3
  UNION ALL
   SELECT   SUBSTR(STRIP(CHAR(PLAN.QUERYNO)), 1, 5) AS QUERY
          , CASE PLAN.PARENT_QBLOCKNO
                 WHEN 0 THEN ' '
                        ELSE
                        SUBSTR(STRIP(CHAR(PLAN.PARENT_QBLOCKNO)), 1, 4)
            END AS PBLK
          , SUBSTR(STRIP(CHAR(PLAN.QBLOCKNO)), 1, 4) AS QBLK
          , SUBSTR(STRIP(CHAR(PLAN.PLANNO)), 1, 4) AS PLNO
          , CASE WHEN PLAN.MIXOPSEQ <> 0
                 THEN SUBSTR(STRIP(CHAR(PLAN.MIXOPSEQ)), 1, 4)
                 ELSE ''
            END CONCAT
            CASE WHEN SORT.SORTNO > 0
                 THEN SUBSTR('ABCDEFGHIJKLMNOPQRSTUVWXYZ',
                             SORT.SORTNO, 1)
                 ELSE ''
            END AS OPSQ
          , PLAN.QBLOCK_TYPE AS TYPE
          , '' AS JOIN
          , 'Sort' AS METHOD
          , CASE TBLS.TABLE_TYPE
                 WHEN 'B' THEN 'Buffer'
                 WHEN 'C' THEN 'CTE'
                 WHEN 'F' THEN 'TabFun'
                 WHEN 'M' THEN 'MQT'
                 WHEN 'Q' THEN 'Temp'
                 WHEN 'R' THEN 'Recurs'
                 WHEN 'T' THEN 'Table'
                 WHEN 'W' THEN 'Work'
                          ELSE ' '
            END AS TYPE
          , SUBSTR(TBLS.CREATOR, 1, 8) AS CREATOR
          , SUBSTR(TBLS.TNAME, 1, 18) AS TABLE
          , SUBSTR(PLAN.ACCESSNAME, 1, 8) AS NDXNAME
          , CASE PLAN.PRIMARY_ACCESSTYPE
                 WHEN 'D' THEN 'D/'
                 WHEN 'T' THEN 'T/'
                          ELSE ''
            END CONCAT
            STRIP(PLAN.ACCESSTYPE)
            AS ACCESS
          , CASE PLAN.PREFETCH
                 WHEN 'S' THEN 'SEQ'
                 WHEN 'L' THEN 'LST'
                 WHEN 'D' THEN 'DYN'
                          ELSE ' '
            END AS PREF
          , CASE PLAN.INDEXONLY
                 WHEN 'Y' THEN 'XO'
                          ELSE ' '
            END AS XO
          , CASE PLAN.MATCHCOLS
                 WHEN 0 THEN ''
                        ELSE SUBSTR(STRIP(CHAR(PLAN.MATCHCOLS)), 1, 2)
            END AS MC
          , SUBSTR(SORT.SORTC, 1, 4) CONCAT
            SUBSTR(SORT.SORTN, 1, 4) AS GJOUGJOU
   FROM     DSN_SORT_TABLE SORT
   JOIN     QUERIES QRYS
        ON  QRYS.QUERYNO = SORT.QUERYNO
   LEFT OUTER JOIN -- Obtain nr of table being sorted
            SORTKEYS SKEY
        ON  SKEY.QUERYNO  = SORT.QUERYNO
        AND SKEY.QBLOCKNO = SORT.QBLOCKNO
        AND SKEY.PLANNO   = SORT.PLANNO
        AND SKEY.SORTNO   = SORT.SORTNO
   LEFT OUTER JOIN -- Obtain name of table being sorted
            TABLES TBLS
        ON  TBLS.QUERYNO = SKEY.QUERYNO
        AND TBLS.TABNO   = SKEY.TABNO
   LEFT OUTER JOIN -- Join back to relevant PLAN_TABLE row
            PLAN_TABLE PLAN
        ON  PLAN.QUERYNO  = SORT.QUERYNO
        AND PLAN.QBLOCKNO = SORT.QBLOCKNO
        AND PLAN.PLANNO   = SORT.PLANNO
        AND(   PLAN.METHOD   = 3
            OR(    PLAN.SORTC_JOIN = 'Y'
               AND SUBSTR(SORT.SORTC, 2, 1) = 'J'
               )
            OR(    PLAN.SORTN_JOIN = 'Y'
               AND SUBSTR(SORT.SORTN, 2, 1) = 'J'
            )  )
   ORDER BY 1, 2 DESC, 3, 4, 5
  ;

---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+-------
QUERY  PBLK  QBLK  PLNO  OPSQ   TYPE    JOIN   METHOD  TYPE    CREATOR   TABLE               NDXNAME   ACCESS      PREF  XO  MC  GJOUGJOU
---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+-------
114    1     3     1            TABLEX         First   Table   DSN8810   DEPT                XDEPT2    I                 XO
114    1     3     2            TABLEX  Innr   NLjoin  Table   DSN8810   EMP                 XEMP1     I                     1
114    1     3     3     A      TABLEX         Sort    Table   DSN8810   EMP                                                        U
114          1     1            SELECT         First   Table   DSN8810   EMP                 XEMP2     I(2)        LST       1
114          1     2            SELECT  L/R    NLjoin  Table   DSN8810   DEPT                XDEPT1    I                     1
114          1     3            SELECT  L/R    NLjoin  Work    TU00001   MANAGERS                      T/R                            J
114          1     3     A      SELECT         Sort    Work    TU00001   MANAGERS                      T/R                            J
114          1     4     A      SELECT         Sort    Table   DSN8810   EMP                                                       O
114          1     4     B      SELECT         Sort    Table   DSN8810   EMP                                                       O
DSNE610I NUMBER OF ROWS DISPLAYED IS 9
DSNE616I STATEMENT EXECUTION WAS SUCCESSFUL, SQLCODE IS 100

Opmerkingen? Vragen? Meer informatie? Klik het onderwerp van uw keuze aan, of e-mail ons met uw vragen.

 

Ten slotte:
ik had slechts een zeer beperkte set explain gegevens tot mijn beschikking. Ik kan dus niet garanderen dat deze queries de explain data ook bruikbaar weergeven voor "echte" SQL uit uw ontwikkel- of productie-omgevingen.
Mocht u een defect vinden, dan hoor ik dat natuurlijk graag.
Ook andere opmerkingen of vragen zijn van harte welkom.

Naar De query
Naar Explain met Range informatie
Naar Explain met Range en Sort informatie.


 

Deze site is aangesloten bij WebRing.
Bekijkt u gerust de lijst van mainframe-gerelateerde sites.
Rennende
    Tyrannosaurus Rex Dino's zijn niet dood. Ze zijn gezond en wel en leven in computer-centra overal om ons heen. Zij spreken in tongen en doen wonderbare magie met computers. Pas op voor de dino! En voor het geval u zit te wachten op het definitieve einde van deze dino's: onthoud dat dino's de wereld 155 miljoen jaren hebben geregeerd!
Dino's en andere anachronismen
[ Aanmelden | Ring Overzicht | Willekeurig | << Vorige | Volgende >> ]