MainframeSupports
tip uge 02/2004:

Nu har SQL syntaksen i mange år givet mulighed for at bruge såkaldte nested table expressions. Hidtil har jeg mest benyttet denne facilitet til at lave GROUP BY på expressions, se eksempelvis uge 36/1999. Her for nylig fandt jeg en anden anvendelse, som rent faktisk giver bedre performance for netop SQL-kald, hvor der benyttes GROUP BY med HAVING kombineret med joins. Ideen illustreres bedst med et eksempel. Først et SQL-kald før optimering:

select c.tbcreator, c.tbname, t.card, count(*)
from sysibm.systables t, sysibm.syscolumns c
where c.tbcreator = t.creator
  and c.tbname = t.name
  and c.coltype = 'INTEGER'
  and c.tbcreator = 'SYSIBM'
  and t.type = 'T'
group by c.tbcreator, c.tbname, t.card
having count(*) > 5

Ovenstående SQL-kald vil virke på din installation. Det finder alle de DB2-tabeller i DB2-kataloget, der har mere end 5 kolonner defineret som INTEGERS og viser for hver tabel antal rækker i tabellen og antallet af INTEGER kolonner. Dette SQL-kald har den funktion, at du selv kan udføre det og, at det er et glimrende eksempel på netop det, som dette tip handler om. DB2 vil udføre ovenstående SQL-kald ved at finde samtlige rækker i SYSIBM.SYSCOLUMNS, der opfylder WHERE betingelsen og joine hver eneste af disse rækker med SYSIBM.SYSTABLES. Først herefter vil alle de resulterende rækker blive behandlet af GROUP BY delen og udvalgt i henhold til HAVING delen.

Følgende SQL-kald vil give nøjagtig samme resultat som det ovenstående SQL-kald:

select c.tbcreator, c.tbname, t.card, c.colcount
from sysibm.systables t,
( select c.tbcreator, c.tbname, count(*) as colcount
  from sysibm.syscolumns c
  where c.coltype = 'INTEGER'
    and c.tbcreator = 'SYSIBM'
  group by c.tbcreator, c.tbname
  having count(*) > 5
) as c
where c.tbcreator = t.creator
  and c.tbname = t.name
  and t.type = 'T'

Dette SQL-kald vil DB2 højst sandsynligt udføre ved først at udføre SELECT'en mod SYSIBM.SYSCOLUMNS og finde de tabeller, der har mere end 5 INTEGER kolonner. Hver af disse rækker vil herefter blive joinet med SYSIBM.SYSTABLES. Den store forskel er, at antallet af joins med SYSIBM.SYSTABLES minimeres drastisk i dette SQL-kald. I det første eksempel foretages der en join for hver eneste INTEGER kolonne, mens der i det andet eksempel kun foretages en join for hver tabel med mere end 5 INTEGER kolonner.

Nu er det bare at finde nogen SQL-kald, der ligner ovenstående. Lignende SQL-kald skal som minimum både involvere en join, en GROUP BY og en HAVING. Uden HAVING giver tippet umiddelbart ingen mening, da man uden HAVING sorterer rækkerne fra i WHERE-delen. Tricket er netop at undgå at joine på rækker, der alligevel elimineres som en del af en HAVING.

Forrige danske tip        Last tip in english        Tip oversigten