En af de ting, der irriterer mest ved DB2, er manglen på kontrol over, hvordan optimizeren vil accesse data. Jeg har i forskellige tip beskrevet nogle få muligheder for at optimere sit SQL, men de tager alle udgangspunkt i, hvordan optimizeren arbejder. Jeg har en enkelt gang beskrevet OPTIMIZE FOR, som i et vist omfang kontrollerer, hvordan DB2 skal accesse data.
I dette tip vil jeg beskrive en fuldt legalt metode til at få kontrol over, hvilken vej DB2 skal foretage en join. Metoden er veldokumenteret, og har eksisteret i et utal af år. Som det fremgår af linket, så omtales metoden i forbindelse med index access, hvor den kan bruges til at få DB2 til at bruge et andet index, end det som optimizeren vil vælge. Hvordan metoden kan udnyttes i forbindelse med joins, vil jeg illustrere med et eksempel, som du kan udføre på et hvilket som helst DB2 subsystem på mainframen. Følgende SQL vil med meget stor sandsynlighed starte med at accesse SYSIBM.SYSTABLES og derefter SYSIBM.SYSCOLUMNS:
Ved at lave følgende SQL kald i stedet, så tvinges optimizeren til at starte med SYSIBM.SYSCOLUMNS for derefter at gå i SYSIBM.SYSTABLES:
Det første statement vil vælge SYSTABLES som den første tabel, fordi den har færrest rækker, og fordi der er et index på TBCREATOR i SYSCOLUMNS. Udtrykket C.TBCREATOR !! '' forhindrer optimizeren i at kunne vælge indexet på TBCREATOR, men da der er et index på CREATOR i SYSTABLES, så vælger DB2 i stedet at gå i SYSCOLUMNS først. Dette eksempel er yderst simpelt og skal kun illustrere metoden. Du kan overbevise dig selv om, at der sker det beskrevne ved at køre EXPLAIN på de to SQL kald og se forskellen. Hvis join kolonnerne er numeriske, så skal du i stedet benytte NUMCOL + 0 som udtryk for at forhindre et index i at blive brugt.
Jeg har kendt dette trick i mange år og har flere gange inden for den sidste tid brugt det med stor succes. Nogle af mine kolleger har også misbrugt det (efter at have set mit held med anvendelsen) med rigtig uheldige konsekvenser. Jeg skal derfor advare mod at bruge løs af det. Optimizeren vælger i langt de fleste tilfælde den bedste accessvej. Det er kun, når du ved, at det er smartere at benytte en anden accessvej, at du skal gribe til dette værktøj. Og husk altid lave en EXPLAIN først for at kontrollere, at effekten er den ønskede.
For at vende tilbage til eksemplet, så er det faktisk ret uhensigtsmæssigt at starte med at accesse SYSCOLUMNS, da den indeholder langt de fleste rækker og dermed vil den samme række i SYSTABLES blive læst mange gange. Når DB2 starter med at accesse SYSTABLES, så bliver hver enkelt række kun læst een gang, og det samme vil gøre sig gældende i SYSCOLUMNS, og dermed er det langt det hurtigste og mest effektive. Så derfor husk at tænke dig godt om, før du begynder at manipulere med dine joins.