News aus der DB2-Welt
Versionen 11 und 12 mit umfangreichen Neuerungen
//
Blog, Data & Analytics
Ende Mai fand in Eindhoven das jährliche DB2-Symposium statt. Eine Session pro Tag beschäftigte sich dabei mit DB2 unter z/OS. Hier wurde besonders auf die Neuerungen eingegangen, die mit den Versionen 11 und 12 geliefert wurden und wie man sie zur Performance-Steigerung nutzen konnte. Desweiteren wurden nützliche neue Features erläutert und wie man sie vernünftig in Praxis anwenden könnte.
Susan Lawson aus Chicago, eine sehr erfahrene DB2-Entwicklerin und IBM Gold Consultant, erläuterte zuerst gekonnt die üblichen Probleme und deren mögliche Lösungen. So wies sie nochmals explizit darauf hin, dass das Sortieren eine der teuersten Aktionen ist und am meisten CPU-Zeit kostet. Auch wenn nur eine Zeile selektiert wird, ist das Sortieren nicht umsonst. Ein weiterer, gerne genommener Fehler ist, dass das einzelne SQL-Statement zwar perfekt sei, aber der Aufruf-Code drumherum nicht und daher viel zu oft aufgerufen werde. Auch dann sind die Kosten enorm und ein umprogrammiertes "schlechteres" SQL-Statement wäre besser, wenn es dagegen nur selten aufgerufen wird. Diese Fehler sind auch vom DB2-Admin nicht zu erkennen, weil er den Aufruf-Code in der Anwendung nicht kennt.
DB2 arbeitet sehr viel mit Statistiken, um den schnellsten Zugriffspfad zu ermitteln. Wenn diese Statistiken aber veraltet sind und SQLs nicht neu gebunden werden, kann das zu erheblichen Performance-Verlusten führen. Daher sind die Statistiken immer aktuell zu halten. Zusätzlich ist es wichtig, die installierten Indizes und deren Zusammensetzung zu kennen. Nur dann kann ein SQL-Statement wirklich performant formuliert werden. In DB2 wird dabei zwischen Index-Matching, Index-Screening, Stage-1 und Stage-2 unterschieden. Beim Index-Matching wird der gesamte Index genutzt und der Zugriff ist höchst performant. Beim Stage-2 findet dagegen ein kompletter TableSpace-Scan statt, der höchst unperformant ist. Äußerst hilfreich ist auch immer ein Blick in die PLAN_TABLE. Dort stehen nicht nur der Zugriffspfad, die verbrauchte CPU-Zeit, der Filter-Faktor, die Kardinalität und der genutzte Index, sondern auch der möglicherweise umformulierte SQL-Code.
Der Optimizer in DB2 ist der "Performance-Hunter" und versucht SQL-Statements so umzuformulieren, dass sie das schnellste Ergebnis liefern. Kenntnisse, wie der Optimizer arbeitet, helfen ernorm dabei, ein gutes SQL-Statement zu schreiben. Unkenntnis darüber, kann die Performance deutlich schwächen. Ein wichtiger Hinweis ist dabei immer wieder, die Performance dadurch zu erhöhen, dass möglichst früh und möglichst viel gefiltert wird. Einige Beispiele, wie der Optimizer umformuliert seien hier genannt:
SELECT COL1, COL2 FROM TAB → SELECT COL1, COL2 FROM TAB
WHERE :HostVar BETWEEN COL1 AND COL2 WHERE COL1 <= :HostVar AND COL2 >= :HostVar
Das so neu formulierte SQL-Statement ist – möglicherweise – Index-Matching! Das alte war dies nicht.
Wichtig für die Filterung ist dabei zu wissen, welche Filterung den größeren Effekt hat. Das Statement
WHERE GESCHLECHT = 'männlich' (Filterung 50%)
AND ORT = 'Münster' (Filterung 99%)
sollte umgeschrieben werden in
WHERE ORT = 'Münster'
AND GESCHLECHT = 'männlich'
Das Prädikat, welches am meisten einschränkt, sollte zuerst genannt werden, denn die Prädikate werden in ihrer codierten Reihenfolge evaluiert.
Weitere Empfehlungen für Umformulierungen (die teilweise in DB2 Version 11 und 12 automatisch durch den Optimizer durchgeführt werden):
QTY * 2 = :HostVar → QTY = INTEGER(:HostVar / 2)
YEAR(date) = 2017 → date BETWEEN '01.01.2017' AND '31.12.2017'
SUBSTR(NACHNAME,1,1) = 'P' → NACHNAME LIKE 'P%'
WHERE COL1 in (1,2) → WHERE COL1 = 1 OR COL1 = 2
Ein neues Konzept in DB2 sind die BOOLEAN TERMS. Mit ihnen kann sehr schnell ein Ergebnis geliefert werden. Dazu ist es notwendig, das SQL-Statement in eine Form zu bringen, die boolesch abgefragt werden kann.
WHERE COL1 = 10 OR COL1 > 10 → WHERE COL1 >= 10 (Boolescher Term)
WHERE NAME > 'Meier' → WHERE NAME >= 'Meier'
OR (NAME = 'Meier' AND(NAME > 'Meier'
AND VORNAME_LIT > 'T') OR (NAME = 'Meier'
AND VORNAME_LIT > 'T'))
Durch das Hinzufügen eines redundanten booleschen Prädikats ist es jetzt ein performanter Boolescher Term.
Neu in der Version 12 ist auch die Minimierung der Sortierung durch die FETCH-FIRST-Klausel. Es werden nur noch die Zeilen sortiert, die ausgewählt worden sind und nicht alle Zeilen, die auf die Zugriffskriterien zutreffen.
Seit der Version 11 gibt es die neue Funktion des CORRELATED REWRITE bei mismatching types. Wenn eine Spalte, die SMALLINT definiert ist mit einer Spalte die INT definiert ist, verglichen wird, war das bisher sehr unperformant. Neuerdings werden die SQL-Statements so umformuliert, dass sie Index-Matching sind.
WHERE COL1 (smallint) = 2 → WHERE COL1 = 2
AND COL2 (int) = COL1 AND COL2 = 2
Diverse weitere Verbesserungen sind in Version 12 enthalten, so z.B. zur Verarbeitung von Triggern, zur In-Memory-Sortierung sowie zur MERGE- und LISTAGG-Performance. Dies kann hier natürlich nur in Ansätzen zeigen, welche Neuheiten die Versionen 11 und 12 bringen.
Zum Abschluss wurde deutlich und das ist wohl ein offenes Geheimnis, dass die Version 12 für längere Zeit die neueste Version bleiben wird, denn sie beinhaltet die größten Änderungen und Optimierungen seit Version 9.