MainframeSupports
tip uge 13/2004:

For lidt over et år siden skrev jeg et tip om, hvordan man kan optimere en OUTER JOIN. Dette tip gav mig senere en ide, som jeg vil skitsere i denne uges tip. Ideen går ud på at omskrive eksisterende programmer med en bestemt IF struktur til OUTER JOIN. Hovedstrukturen i sådanne programmer er et SQL-kald, der finder de rækker, som skal behandles. For nogen af disse rækker skal der hentes yderligere informationer i en eller flere andre tabeller. Det ser typisk således ud:

EXEC SQL DECLARE MAINCURSOR CURSOR FOR
  SELECT COLUMNA, ..., COLUMNX
  FROM MAIN_TABLE;
EXEC SQL OPEN MAINCURSOR;
EXEC SQL FETCH MAINCURSOR ...;
WHILE SQLCODE = 0 DO
  EXTRA = ''
  IF MAINCURSOR.COLUMNX = 'MORE INFO NEEDED'
  THEN DO
    EXEC SQL
      SELECT EXTRA INTO :EXTRA
      FROM MORE_INFO_TABLE
      WHERE KEYCOLUMN = :MAINCURSOR.COLUMNA;
  END
  /* DO MORE WITH ALL GATHERED INFORMATION */
  EXEC SQL FETCH MAINCURSOR ...;
END
EXEC SQL CLOSE MAINCURSOR;

Ovenstående programlogik kan med en OUTER JOIN forenkles til:

EXEC SQL DECLARE MAINCURSOR CURSOR FOR
  SELECT MAIN.COLUMNA, ..., VALUE(MORE.EXTRA, '')
  FROM MAIN_TABLE MAIN
  LEFT OUTER JOIN MORE_INFO_TABLE MORE
  ON MAIN.COLUMNX = 'MORE INFO NEEDED'
  AND MAIN.COLUMNA = MORE.KEYCOLUMN;
EXEC SQL OPEN MAINCURSOR;
EXEC SQL FETCH MAINCURSOR ...;
WHILE SQLCODE = 0 DO
  /* DO MORE WITH ALL GATHERED INFORMATION */
  EXEC SQL FETCH MAINCURSOR ...;
END
EXEC SQL CLOSE MAINCURSOR;

Pist væk er IF statementet i programmet og MAINCURSOR er forvandlet til en OUTER JOIN. Resultatet af programlogikken i de to programstumper er nøjagtig det samme. Så kan man begynde at diskutere, hvad der er kønnest og hvad der performer bedst. I mine øjne er der ingen tvivl om at OUTER JOIN eksemplet giver den mest overskuelige logik, selv om MAINCURSOR er blevet lidt mere kompliceret at forstå.

Langt mere interessant er performance for de to eksempler. I begge eksempler vil MAINCURSOR returnere lige mange rækker. Antallet af FETCH kald er altså det samme. I begge tilfælde vil COLUMNX blive undersøgt for alle rækker og antallet af opslag i tabel MORE_INFO_TABLE vil også være det samme. Det man sparer med OUTER JOIN er de ressourcer, der skal til for at udføre det ekstra SQL-kald i det oprindelige eksempel. Hvis det ekstra SQL-kald skal udføres mange gange, så er besparelsen stor, mens det nok ikke er værd at skrive programmet om, hvis under 10% af rækkerne i MAINCURSOR udløser det ekstra SQL-kald.

Jeg har målt lidt på ideen og det er ikke en ide, der giver vilde besparelser, som man ellers nogen gange kan opleve med DB2. Jeg vil typisk tro, at man kan spare 10%-30% ved at bruge OUTER JOIN metoden i stedet for IF statementet, alt afhængig af hvor mange ekstra SQL-kald man sparer. I version 4 af DB2 og også i nogen tilfælde i version 5 vil ovennævnte omskrivning resultere i langt dårligere performance, så jeg kan kun anbefale ideen for DB2 version 6 og fremefter.

Forrige danske tip        Last tip in english        Tip oversigten