Inhaltsverzeichnis 1 Einleitung
2 Tuning einer Datenbank aus der Sicht des Programmierers
2.1 SQL-Tuning
2.1.1 Wichtige Kriterien für die Optimierung
2.1.2 Der Optimizer
2.1.3 Tuning per Hand
2.1.4 Teilen des SQL-Statements
2.1.5 Die Reihenfolge der Tabellennamen
2.1.6 Die Reihenfolge der Kondition im WHERE-Statement
2.1.7 Optimierung des Zugriffs auf die Datenbank
2.1.8 DECODE-Statement
2.1.9 Weitere Tips zur Verbesserung der Performance
2.1.10 Nutzung von Indexen
2.2 PL/SQL Tuning
2.3 SQL*Forms Tuning
3 Fazit
Inhalt
1 Einleitung
In einem großen Datenbanksystem spielt die
Performance der Datenbank eine sehr große Rolle. Angefangen von der Systemplanung, der
Programmierung bis hin zum Testen des fertigen Programms darf die Performance eines
Systems nicht vernachlässigt werden. Jede Veränderung des Datenbanksystems kann die
Performance beeinträchtigen. Ziel des Tunings ist, daß die Organisation bzw. die
Anwender finanzielle und menschliche Vorteile voll ausschöpfen können, wobei der
Neuerwerb von Hardware nicht erforderlich ist. Mittels Tuning wird die Antwortzeit des
Systems verkürzt, so daß lange Wartezeiten entfallen und effizienter gearbeitet werden
kann.
Verantwortlich für die Performance einer Datenbank ist sowohl der Systemadministrator als
auch der Systemplaner/-manager, der Designer, der Programmierer, der
Datenbankadministrator und der Systemadministrator.
Die Ursachen einer schlechten Datenbankperformance können vielfältig sein. Sie werden
unterteilt in die Bereiche: Design und Entwicklung, System Ressourcen, Speicherprobleme,
Disk I/O-Probleme, CPU Auslastungsprobleme und Netzwerkprobleme.
In den nächsten Kapiteln wird das Tuning aus der Sicht des Programmierers, insbesondere
des SQL-Tunings, weiter vertieft.
Der Programmierer ist verantwortlich für
die Entwicklung einer Applikation und für die Verbesserung der Antwortzeit bzw. der
Kapazitätsauslastung des entsprechenden Programmes. Dieses Ziel kann bei einer Datenbank
durch die Optimierung des sogenannten SQL-Statements ( Structured Query Language =
Sprache zur Definition bzw. Manipulation von Datenbanken) erreicht werden.
In dieser Arbeit wird SQL von ORACLE Datenbanksystem verwendet (ORACLE 6 und 7). Bei einer
ORACLE Datenbank hat der Programmierer 2 Möglichkeiten, das System zu optimieren: das
SQL-Statement selbst und/oder die darauf aufbauenden Werkzeuge, d.h. PL/SQL und SQL*Forms.
Das Optimieren von SQL selbst wird im Abschnitt 2.1 besprochen. Das Optimieren der beiden
Werkzeuge wird im Abschnitt 2.2 und 2.3 kurz skizziert.
Es bieten sich mehrere Möglichkeiten, das
SQL-Statement anzugeben. Die Wahl von SQL ist dann korrekt, wenn die gestellten Fragen
schnellstmöglich beantwortet werden können, ohne daß die Leistung des Systems hierdurch
benachteiligt wird. Das SQL-Statement ist so zu programmieren, daß es effizient und
schnell in jeder Applikation laufen kann.
Vor der SQL-Optimierung müssen zunächst jedoch einige Fragen beantwortet werden, die
für die Optimierung von großer Bedeutung sind.
Für die Optimierung eines Datenbanksystems
müssen folgende Aspekte beachtet werden:
Je geringer der Zugriff auf die physischen Datenbankblöcke ist, desto weniger muß
eingelesen werden, desto schneller arbeitet die Datenbank.
Das Datenbankdesign ist von großer Bedeutung, die nicht unterschätzt werden darf.
Bestehen Wissenslücken über das Design, so kann der Versuch der Optimierung ins
Gegenteil umschlagen. Zudem muß von Beginn an die zukünftige Planung des Systems
berücksichtigt werden.
Zu Beginn sollte definiert werden, welche Schnelligkeit erreicht werden muß.
Das Datenvolumen darf bei der Optimierung nicht unterschätzt werden. Bei einer
Testdatenbank ist das Volumen verhältnismäßig gering, so daß es der realen Applikation
nicht entspricht.
Die Optimierung stellt einen fortlaufenden Prozeß dar, d.h. bei jeder Änderung
(Indexänderungen, neue Felder, usw.) muß die Applikation bzw. das SQL-Statement neu
optimiert werden.
Der Optimizer berechnet den optimalen
Ausführungspfad eines SQL-Statements. Um diesen optimalen Ausführungspfad zu erreichen,
sucht der Optimizer nach folgenden Informationen:
detaillierte Syntax des SQL-Statements,
Bedingungen, die erfüllt sein müssen (WHERE-Klausel),
Datenbanktabellen, auf die zugegriffen werden muß,
Indexe, welche in der Datenbank vorhanden sind,
Hints (Nur bei ORACLE 7),
Statistiken, die vom ANALYZE-Befehl erstellt worden sind (Nur bei ORACLE 7).
Bei dem Versuch, die Leistung eines Datenbanksystems zu verbessern, müssen SQL-Statements
miteinander verglichen werden. Der Vergleich dient der Auslese der schnellsten bzw.
effizientesten SQL-Statements. Für diesen Vergleich stellt ORACLE eine EXPLAIN
PLAN-Diagnose-Befehl zur Verfügung. Durch diesen Befehl besteht die Möglichkeit, den
inneren Optimierungsvorgang zu beobachten, verschiedene SQL-Statements durchzuführen, um
dann die Ergebnisse miteinander vergleichen zu können.
ORACLE bietet zwei Alternativen zur Optimierung von SQL:
Optimierung mittels Regeln (rule-based Optimizer).
Hierbei werden die Indexe und die vordefinierten Regeln benutzt, um den optimalen Pfad zu
berechnen. (Z.Bsp.: wenn eine Spalte in der Datenbank einen Index besitzt, so benutzt der
Optimizer diesen Index, ohne noch einmal zu überprüfen, ob dieser Index wirklich eine
Verbesserung der Leistung bewirkt). Diese Methode ist bei ORACLE 6 und 7 vorhanden.
Kostenbasierte Optimierung (cost-based Optimizer).
Dies ist eine verbesserte Optimierungsmethode. Hierbei werden die Informationen benutzt,
die in der Datenbank vorhanden sind (Tabellengröße, Anzahl der Datensätze, Verteilung
des Schlüssels). Diese Informationen sind vorhanden, nachdem der ANALYZE-Befehl für die
Tabellen durchgeführt wurde. Der ANALYZE-Befehl sammelt Statistiken über die Tabellen,
Datenmenge, Indexe und speichert sie in der Data-Dictionary der Datenbank ab. Diese
Methode ist nur bei ORACLE 7 vorhanden.
In der Version 7 von ORACLE kann explizit gesagt werden, welche Optimierungsmethode
benutzt werden soll.
Abgesehen von diesen beiden Optimierungsmethoden muß beachtet werden, daß der Optimizer
nicht allwissend ist. So erkennt der Optimizer nicht, wie eine Datenbank konstruiert ist
oder welche Funktion eine Datenbank besitzt.
Mit der Version 7 von ORACLE kann SQL auch
per Hand optimiert werden. Mittels einer Bemerkung wird die Entscheidung des Optimizers
überschrieben. So wird nun, anstelle des zuvor vom Optimizer berechneten Pfades, ein
alternativer Pfad durchgeführt, z.Bsp.: SELECT ... FROM /*+ RULE */ FROM EMP, DEPT WHERE
... Diese Bemerkung /*+ RULE */ bedeutet, daß der Optimizer nun die Optimierung
mittels Regeln anstatt der kostenbasierten Optimierung nutzt.
Nachdem der optimale Ausführungspfad für
das SQL-Statement berechnet wurde, behält die ORACLE Datenbank sie im Speicher, da diese
Berechnung ein lang andauernder Prozeß ist. Es gibt zwei unterschiedliche Methoden, wie
diese Speicherung stattfindet:
Program-Global-Area für ORACLE 6.
Jeder Prozeß bzw. jedes Programm hat seinen eigenen Speicherbereich. Jedes SQL-Statement,
welches durchgeführt wird, wird in diesem Bereich gespeichert. Wenn der gleiche Benutzer
bzw. das gleiche Programm ein gleiches SQL-Statement erneut abschickt, so wird erst in dem
Speicherbereich gesucht. Wenn dort das gleiche SQL-Statement gefunden wird, so braucht das
System den optimalen Ausführungspfad nicht noch einmal zu berechnen.
System-Global-Area für ORACLE 7.
Bei diesem System gibt es nur einen einzigen gemeinsamen Speicherbereich. D.h., alle
Benutzer bzw. alle Programme greifen auf den gleichen Bereich zu. Diese Methode ist
vorteilhaft, da alle Benutzer bzw. alle Programme das SQL-Statement erst in dem
gemeinsamen Speicherbereich suchen. Wird das gleiche SQL-Statement gefunden, so braucht
das System den optimalen Ausführungspfad nicht noch einmal zu berechnen.
Leider existiert ein Schwachpunkt bei ORACLE. ORACLE führt einen reinen Stringsvergleich
durch, d.h.: Leerzeichen, Groß- und Kleinschreibung sind von Bedeutung, z.Bsp.: SELECT * FROM
EMP ist nicht identisch mit SELECT * from EMP.
Eine der wichtigsten Möglichkeiten für
die Optimierung unter ORACLE 6 besteht in der Reihenfolge der Tabellennamen, so daß das
SELECT-Statement so effizient wie möglich ausgewählt wird. Bei ORACLE 7 wird diese
Möglichkeit nicht oft genutzt, da auf die obengenannte kostenbasierte Optimierung
zurückgegriffen wird.
Wenn mehr als zwei Tabellen in der FROM-Klausel des SELECT-Statements benutzt werden,
z.B.: SELECT COUNT (*) FROM EMP, DEPT, so ist die Reihenfolge der Tabellen von großer
Bedeutung für die Performance.
Wenn das System die Optimierung mittels Regeln benutzt, so kann es keine intelligente
Entscheidung treffen. Es benutzt einfach die Reihenfolge der Tabellennamen. In dem
obengenannten Beispiel verarbeitet das System erst die DEPT Tabelle, dann die EMP Tabelle
(von rechts nach links).
Die Tabelle, die als Erste eingelesen wird, nennt man Lenktabelle. Unter ORACLE 6 ist es
sehr wichtig, welche Tabelle als Lenktabelle benutzt wird. ORACLE 6 benutzt intern eine
sort/merge-Prozedur (Sortier- und Mischprozedur), um zwei Tabellen zu verbinden. Zuerst
wird die erste Tabelle, also die Lenktabelle gelesen und sortiert, dann die zweite
Tabelle. Anschließend werden die Reihen von der zweiten Tabelle mit der ersten Tabelle
gemischt. Wenn die Lenktabelle (DEPT) sehr groß (z.B.: 16.000 Datensatz) und die zweite
Tabelle (EMP) sehr klein ist (z.B.: 1 Datensatz), dann ist das Sortieren von der
Lenktabelle sehr aufwendig. Dieser Vorgang beeinträchtigt die Geschwindigkeit. Zum
Vergleich: mit der großen Lenktabelle braucht das System 26 Sekunden, um SELECT COUNT (*)
FROM EMP, DEPT durchzuführen, wobei im umgekehrten Fall (SELECT COUNT (*) FROM DEPT, EMP)
das System nur 0,9 Sekunden braucht. Deshalb ist die Auswahl der Lenktabelle von großer
Bedeutung. Mit ORACLE 7 existiert dieses Problem nicht, da das System intelligent genug
ist, um selbständig auszuwählen, welche Lenktabelle es benutzt. Sollen drei Tabellen
miteinander verbunden werden, so sollte die Tabelle, welche die meisten Abhängigkeiten zu
den anderen beiden Tabellen besitzt (Schnittabellen), zur Lenktabelle ausgewählt werden.
Die Reihenfolge der Kondition im
WHERE-Statement stellt ebenfalls eine Möglichkeit der Optimierung dar. Bei ORACLE 6 ist
es wichtig, wie die Reihenfolge der Kondition spezifiziert wird. Bei ORACLE 7 ist die hier
beschriebene Optimierungsmethode nur relevant für das manuelle Tuning des SQL-Statements.
Wie unter Punkt 2.1.2 beschrieben, basiert die Optimierung mittels Regeln auf
vordefinierten Regeln. Wie diese Regeln verteilt sind, kann von der sogenannten
Zustandstabelle abgelesen werden. ORACLE benutzt diese Zustandstabelle, um berechnen zu
können, welcher Index für die Berechnung des optimalen Pfades benutzt werden soll.
Der erste Rang in dieser Zustandstabelle ist die ROWID = Konstante, d.h.: der Optimizer
benutzt den Index von ROWID, wenn dieses Statement vorhanden ist. Wenn zwei Indexe
innerhalb einer Tabelle benutzt werden, so entscheidet sich ORACLE, indem es die Ränge
der Zustände miteinander vergleicht. Benutzt wird der Zustand mit dem höheren Rang.
Sollten die beiden Indexe jedoch denselben Rang besitzen, so benutzt ORACLE die
Reihenfolge der Kondition im WHERE-Statement.
Das ROWID-Statement stellt die schnellste Methode zum Wiederfinden von Datensätzen dar.
Es sollte generell immer das ROWID-Statement benutzt werden, um ein schnelles Ergebnis zu
erreichen.
Jedesmal wenn ein SQL-Statement ausgeführt
wird, muß ORACLE mehrere interne Operationen durchführen. D.h., daß das Statement
eingelesen werden muß, die Indexe analysiert und die Datenblöcke gelesen werden müssen.
Je größer die Reduktion dieses Vorganges ist, desto geringer ist der Ballast der
Datenbank. Besonders wichtig ist die Optimierung des Zugriffs, wenn das System als
Client/Server eingesetzt wird. Ein Client/Server-System verfolgt immer das Ziel, den
Verkehr im Netzwerk zu reduzieren, so daß die Antwortzeiten der Programme gering sind.
Eine Verbund-Operation (z.B.: von zwei Tabellen) ist normalerweise effektiver als zweimal
ein SQL-Statement durchführen zu lassen oder aber den Gebrauch des Cursors und zweimal
Einfügen (FETCH-Operation).
Es wird oft eine Methode benötigt, um die
Anzahl der Datensätze bzw. die Summe von bestimmten Spalten zu berechnen. Das
DECODE-Statement stellt eine sehr effiziente Methode hierfür dar. Mit dem
DECODE-Statement kann verhindert werden, daß mit der gleichen Tabelle eine
Verbund-Operation durchgeführt werden muß oder die Selektion von gleichen Datensätzen
mehrmals ausgeführt wird. Das DECODE-Statement kann auch im ORDER BY- und im GROUP
BY-Statement benutzt werden. Anstatt mehrmals gleiche SQL-Statements mit verschiedenen
ORDER BY- bzw. GROUP BY-Statements anzugeben, kann das DECODE-Statement benutzt werden. Es
ist zu beachten, daß das DECODE-Statement keinen Index benutzen kann, d.h. es benutzt
eine interne sort/merge-Prozedur. Weil dies ein langsamer Prozeß ist, sollte es nur
benutzt werden, wenn die Anzahl der Datensätze gering ist, die durch das WHERE-Statement
zurückgegeben wurden.
In diesem Teil werden noch einige Tips
angegeben, welche zur Verbesserung der Performance des SQL-Statements beitragen können.
Vereinigung von einfachen, nicht zueinander in Beziehung stehender Datenbankzugriffe:
Die Performance läßt sich verbessern, indem mehrere einfache SQL-Statements vereinigt
werden. Geschieht dies nicht, so wird ein SQL-Statement mehrmals ausgeführt, das System
muß das Statement immer wieder einlesen, verarbeiten und entsprechende Datensätze lesen.
Folglich würde dies zu einer Verschlechterung der Durchlaufgeschwindigkeit im Netzwerk
führen.
Löschen von doppelten Datensätzen:
Um dies effizient zu erreichen, sollte das ROWID-Statement benutzt werden. Dieses
Statement arbeitet effizient, um die gleichen EMP_NO Datensätze in der Tabelle EMP zu
löschen:
DELETE FROM EMP E
WHERE E.ROWID > ( SELECT MIN(X.ROWID)
FROM EMP X
WHERE X.EMP_NO = E.EMP_NO)
Berechnung der Anzahl der Datensätze von der Tabelle (COUNT-Statement):
Die Reihenfolge der Effizienz des COUNT-Statements ist wie folgt definiert: COUNT (auf
einer indizierten Spalte) ist das schnellste, COUNT (*) ist das zweitschnellste und COUNT
(1) ist das langsamste Statement.
Nutzung von WHERE anstatt HAVING:
Generell sollte das HAVING-Statement vermieden werden, da das HAVING-Statement die
ausgewählten Datensätze herausfiltert, nachdem es alle Datensätze gelesen, sortiert
oder summiert hat.
Tuning von Views:
Die Performance des Views kann auch wie ein normales SQL-Statement optimiert werden.
Minimierung des Tabellenzugriffs in einer Abfrage:
Um die Performance zu verbessern, kann der Tabellenzugriff in einer Abfrage minimiert
werden, insbesondere wenn in dem SQL-Statement sub-query-SELECT (Abfrage in einer Abfrage)
oder mehrere Spalten UPDATE-Statement vorkommen.
Nutzung von Alias:
Es sollte immer Alias benutzt werden, wenn mehrere Tabellen im SQL-Statement vorhanden
sind. Erstens verringert dies die Verarbeitungszeit des SQL-Statements, zweitens
verhindert dies Syntaxfehler, die von mehrdeutigen Namen verursacht werden.
Nutzung von NOT EXIST anstatt NOT IN:
In sub-query-Klausel verursacht NOT IN intern eine sort/merge-Prozedur. Diese ist dann
nicht effizient.
SELECT ...
FROM EMP
WHERE DEPT_NO NOT IN (SELECT DEPT_NO
FROM DEPT
WHERE DEPT_CAT = 'A')
verursacht eine sort/merge-Prozedur-Berechnung. Für die Verbesserung der Performance muß
dies ersetzt werden durch:
SELECT ...
FROM EMP E
WHERE NOT EXIST (SELECT *
FROM DEPT
WHERE DEPT_NO = E.DEPT_NO
AND DEPT_CAT = 'A')
Nutzung von Verbundoperationen anstatt EXIST:
Wenn möglich, sollten generell Verbundoperationen für die Benutzung von EXIST mit
sub-query-Klausel bevorzugt werden.
Nutzung von EXIST anstatt DISTINCT:
Dieses Beispiel:
SELECT DISTINCT DEPT_CODE, DEPT_NAME
FROM DEPT D, EMP E
WHERE D.DEPT_CODE = E.DEPT_CODE
ist weniger effizient als:
SELECT DEPT_CODE, DEPT_NAME
FROM DEPT D
WHERE EXIST ( SELECT *
FROM EMP E
WHERE E.DEPT_CODE = D.DEPT_CODE).
EXIST ist in diesem Fall schneller, da der Datenbank-Kernel erkennt, daß die
sub-query-Klausel bereits einmal erfüllt ist. Hiernach kann die Abfrage terminiert
werden.
Allgemein gibt es zwei verschiedene
Methoden, um Datensätze von der Tabelle wiederzufinden: Nutzung von Indexen und full
table scan (sequentielles Lesen von der Tabelle ohne Index). Beide Methoden haben ihre
Stärken und Schwächen. Es kann nicht generell gesagt werden, daß die Nutzung von
Indexen immer schneller als full table scan ist.
Full table scan kann effizient sein, da es eine geringere Bewegung des Plattenkopfes
erfordert. Der Kopf der Festplatte liest die Datenblöcke sequentiell vom Anfang bis zum
Ende. Ein indizierter Zugriff holt die Datensätze in logischer Folge, und nicht nach der
Art und Weise, wie sie physisch auf der Festplatte gespeichert sind. Unter Umständen
können aus diesem Vorgang viele Bewegungen des Plattenkopfes resultieren. Die
Entscheidung zwischen Nutzung von Indexen und von full table scan hängt dann von der
Größe der Tabelle und von dem Muster des Zugriffs auf die Tabelle ab. Die Hersteller von
ORACLE empfehlen, full table scan statt eines indizierten Zugriffs zu benutzen, wenn das
SQL-Statement bzw. die Abfrage von Tabellen weniger als acht Datenblöcke beinhaltet. Für
größere Tabellen ist normalerweise ein indizierter Zugriff schneller als full table
scan.
Bei einem SQL-Statement, das nur die indizierten Spalten oder Pseudospalten (USER,
COUNT(*), usw.) in der Tabelle benutzt, kann davon ausgegangen werden, daß die Nutzung
des indizierten Zugriffs schneller ist. In diesem Fall wird nur der Index gelesen. Die
physischen Datensätze werden nicht gelesen.
Gelegentlich ist es effizienter, erst den Index in der Tabelle zu löschen, wenn viele
Datensätze in eine Tabelle einfügt werden sollen. Nach dem Einfügen kann der Index
wiederherstellt werden. Dieser Vorgang ist effizienter, da sonst nach dem Einfügen eines
Datensatzes der Index jedesmal neu aktualisiert wird.
Es gibt keine absolute Richtlinie zur Nutzung von Indexen oder full table scan. Es sollte
immer eine Tabellensituation zuvor überprüft werden.
Zusätzlich muß folgendes für die Optimierung beachtet werden:
Kombination von Indexen:
Nutzung von zu vielen Indexen in einer Tabelle kann die Performance verschlechtern. ORACLE
verschmelzt bzw. kombiniert den Index für eine Tabelle, solange es kann. Wenn ein
SQL-Statement über zwei oder mehrere gleiche Indexe in verschiedene Tabellen in dem
Ausführungspfad verfügt, so benutzt ORACLE beide Indexe. Diese Indexe werden gemischt,
und nur die Datensätze, die gemeinsam zu den Indexen gehören, werden gelesen.
Wenn die beiden Indexe in der gleichen Tabelle in einem WHERE-Statement existieren,
berechnet ORACLE erst den Rang. Ein Index mit UNIQUE-Statement hat einen höheren Rang als
ein Index ohne UNIQUE-Statement. Wenn beide Indexe ein UNIQUE- bzw. kein UNIQUE-Statement
besitzen, so ist der Rang abhängig davon, ob die Indexe sich in der gleichen oder in
verschiedenen Tabellen befinden. Wenn zwei gleiche Indexe in zwei verschiedenen Tabellen
existieren, so bestimmt die Tabellenreihenfolge die Bearbeitungsfolge. Wenn zwei gleiche
Indexe in zwei gleichen Tabellen existieren, so erhält der erste Index im WHERE-Statement
den höheren Rang (die Reihenfolge in WHERE-Statement).
Es sollte beachtet werden, daß ein UNIQUE- (oder non UNIQUE-) WHERE-Vergleich einen sehr
hohen Rang bei dem Optimizer besitzt, aber nur, wenn der Vergleich zwischen Konstanten
bzw. Variablen stattfindet.
Wenn die Indexe die Prädikate Gleichheit und Ungleichheit gleichzeitig in einer Tabelle
benutzen, kann ORACLE diese Indexe nicht mischen. In diesem Fall benutzt es nur das
Prädikat Gleichheit. Bei einem unklaren Rangsieger benutzt ORACLE den ersten Index
im WHERE-Statement.
Ausschalten von bestimmten Index:
Beispiel:
SELECT ...
FROM EMP
WHERE EMP_TYPE = 'A'
AND EMP_CLASS = 'X'.
Die Spalte EMP_TYPE ist indiziert (non-UNIQUE) und EMP_CLASS ist nicht indiziert. Der
Optimizer merkt, daß EMP_TYPE indiziert ist und benutzt diesen Index. Wird später ein
zweiter Index (non-UNIQUE) auf EMP_CLASS eingefügt, so wird der Optimizer beide Indexe
benutzen, indem er eine sort/merge-Prozedur ausführt. Dies kann unter Umständen zu einer
Verschlechterung der Performance führen. In diesem Fall kann der Index von EMP_CLASS von
der Betrachtung des Optimizers wie folgt (mit dem || Operator) ausgeschaltet werden:
SELECT ...
FROM EMP
WHERE EMP_TYPE = 'A'
AND EMP_CLASS || = 'X'.
Vermeidung einer Berechnung auf einer indizierten Spalte:
Generell benutzt der Optimizer keinen Index, sondern full table scan, wenn die indizierte
Spalte ein Teil von einer Funktion (im WHERE-Statement) ist. MIN- und MAX-Funktionen
bilden eine Ausnahme.
Automatisches Ausschalten von Indexen:
Unter bestimmten Umständen schaltet das System besondere Indexe aus. Z.B.: Eine Tabelle
besitzt zwei oder mehrere Indexe. Einer der Indexe ist UNIQUE und der andere ist
non-UNIQUE. In diesem Fall nutzt ORACLE nur den UNIQUE-Index und ignoriert den anderen.
Einfügen von Spalten in einem Index:
Gelegentlich ist es effizienter, eine zusätzliche Spalte in einen Index zu integrieren.
Dies ist empfehlenswert, wenn die Spalte klein ist (kein 30-String Feld) und oft benutzt
wird. In allen anderen Fällen lohnt es sich nicht.
Vermeidung von NOT in einer indizierten Spalte:
Allgemein sollte die Nutzung eines NOT-Vergleichs in einer indizierten Spalte verhindert
werden, da ORACLE ansonsten full table scan anstatt dem Index benutzt. In bestimmten
Fällen transformiert ORACLE NOT-Operator zu mit diesen korrespondierenden Funktionen
(z.B.: NOT > zu <=, usw.).
Nutzung von UNION statt OR:
Generell sollte ein UNION-Statement (im WHERE-Statement) benutzt werden, wenn die Spalten
indiziert sind. Die Nutzung von OR auf indizierten Spalten verursacht ein full table scan
anstatt eines indizierten Wiederfindens.
Vermeidung von Null-Werten in Indexen:
Ein Null-Wert kann nicht verglichen werden. Deshalb sollte er als Teil von Indexen
vermieden werden. Die Nutzung von Null-Werten an einer falschen Stelle kann zu einer
Verschlechterung der Performance führen. Die Nutzung von Null-Werten kann auf einer
indizierten Spalte das indizierte Suchen unterlassen, so daß statt dessen ein full table
scan stattfindet, weil Null-Werte nicht zu der Domäne von Indexen gehören.
Nutzung von Null-Werten für eine Markierung:
Obwohl normalerweise die Nutzung von Null-Werten Probleme beinhaltet, können sie sehr
effizient für eine Markierung (flag) benutzt werden. Anstatt irgendeine Variabel zu
benutzen, welche den Speicherplatz beansprucht, können Null-Werte benutzt werden.
Null-Werte werden nicht im Index gespeichert, so daß auf diesem Weg Speicherplatz gespart
werden kann.
PL/SQL (Procedure Language/SQL) ist eine
Reihe von Prozeduren, die die Möglichkeiten des SQL-Statements erweitern. PL/SQL kann mit
SQL kombiniert werden, um die Programmierung der Applikation zu vereinfachen. PL/SQL
verbessert die Performance, insbesondere bei dem Datenbankzugriff auf ein Netzwerksystem,
da PL/SQL mehrere SQL-Statements auf einen Block komprimiert. PL/SQL optimiert den
Zugriff, indem der gesamte Block auf einmal abgeschickt wird. Die Nutzung von PL/SQL ist
unter Umständen besonders effizient bei einem Batch-Update. Mittels PL/SQL kann die
Performance verbessert werden, es sind jedoch bestimmte Aspekte zu beachten. Hierfür ist
primär das zugrundeliegende SQL-Statement zu überprüfen, da sich hier die meisten
Probleme befinden.
SQL*Forms wird benutzt, um eine
interaktive, formularbasierte Applikation zu erstellen. Es besteht die Möglichkeit, das
SQL-Statement und PL/SQL in SQL*Forms zu integrieren. Um SQL*Forms zu optimieren, sollte
wie bei PL/SQL das zugrundeliegende SQL-Statement als erstes überprüft werden, da sich
hier 90% der Probleme befinden. Es gibt mehrere Aspekte, die bei der Optimierung von
SQL*Forms beachtet werden müssen. Eine Ausführung dieser Aspekte würde jedoch den
Rahmen dieser Arbeit sprengen.
Tuning eines Datenbanksystems, insbesondere
SQL-Tuning, verlangt eine kontinuierliche Arbeit. Die Performance eines Systems muß
fortwährend beobachtet und analysiert und der Situation entsprechend angepaßt werden.
Die Veränderung von Tabellenvolumen, der Anzahl der zur Verfügung stehenden Indexe und
der physischen Lage stellen die Ursache dar, daß das SQL-Statement jedesmal neu angepaßt
werden muß. Zusätzlich bieten neue Versionen von ORACLE jedesmal neue Möglichkeiten zur
Optimierung.
Die Optimierungsverfahren, von Optimierung mittels Regeln bis zu der kostenbasierten
Optimierung, werden fortlaufend verbessert. Zusätzlich bietet sich dem Programmierer
noch die Möglichkeit, per Hand weiter zu optimieren. Bei der Benutzung der von ORACLE
angebotenen Werkzeuge sollte darauf geachtet werden, daß die Ursache einer schlechten
Performance bei dem zugrundeliegende SQL-Statement liegen kann.
Die Optimierung der Performance eines Datenbanksystems ist grenzenlos. Daher muß das Ziel
der Performance selbst definiert werden, da sich die Optimierung des SQL-Statements nur
bis zu einem bestimmten Punkt lohnt. Hiernach steht die zu erbringende Zeitinvestition
für die Optimierung in keiner Relation zu den immer weiter sinkenden Hardwarekosten. |