Oracle Tuning in der Praxis

Oracle Tuning in der Praxis
Oracle Tuning in der Praxis
Frank Haas
Rezepte und Anleitungen für Datenbankadministratoren und
-entwickler
ISBN 3-446-40725-1
Leseprobe
Weitere Informationen oder Bestellungen unter
http://www.hanser.de/3-446-40725-1 sowie im Buchhandel
3
3 Das ABC des Tuning
In diesem Kapitel versehen wir uns mit den Grundlagen, die Sie für das Tuning
benötigen. Diese umfassen verschiedene Kennzahlen, (Wait) Events, Statistiken,
Ratios und einige ausgewählte V$-Views, auf die Sie beim Tuning immer wieder
zugreifen werden.
Die eigentlichen Tools und Techniken, die für das Tuning benötigt werden, werden dann
ab dem nächsten Kapitel besprochen.
3.1
Ratios oder Wait Interface?
Es gibt vereinfacht gesagt zwei Schulen für das Tuning. Die ältere verwendet bestimmte
Kennzahlen und Ratios, um ein Bild über die Performanz der Datenbank zu erhalten. Die
zweite ein wenig neuere Schule benutzt vornehmlich das Oracle Wait Interface, um zu sehen, in welchem Bereich es Performanzprobleme gibt. Die beiden Schulen verstehen sich
manchmal nicht so richtig gut, aber wir schauen uns beides an, die Ratiotechnik aber vor
allem aus historischen Gründen.
Die Ratios haben heute nicht mehr die gleiche Aussagekraft wie früher, da sich die Semantik vieler Kennzahlen – wie zum Beispiel 'physical reads' – über die Jahre geändert hat. Die
Ratios existieren aber nach wie vor, auch in den Oracle-Auswertungen in 10g wie zum
Beispiel im Automatic Workload Repository finden Sie die Ratios noch. Seit Oracle 10g
werden viele Ratios schon automatisch berechnet, das gab es in früheren Versionen nicht.
Seit dieser Version werden jede Minute die Cache Hit Ratios über die neuen V$-Views,
die sich auf die Metriken beziehen (V$SYSMETRIC, V$SESSMETRIC, V$EVENTMETRIC, V$FILEMETRIC, V$WAITCLASSMETRC, V$METRICNAME), aktualisiert.
Das Oracle Wait Interface verfolgt einen ganz anderen Ansatz und hat den großen Vorteil,
dass es da ansetzt, wo den Anwender der Schuh drückt: an der Antwortzeit. So habe ich
bei den Firmen, die ich wegen irgendwelcher dringender Performanzprobleme zum Oracle
Tuning besuchte, im Regelfall immer exzellente Hit Ratios erlebt, das war nie das Prob-
95
3 Das ABC des Tuning
lem. Vielleicht muss man es so ausdrücken: Gute Hit Ratios sind keine Garantie, dass es
schnell läuft.
Das Wait Interface wird manchmal auf die vier V$-Views, die mit 7.0.12 eingeführt wurden, eingeschränkt: V$SYSTEM_EVENT, V$SESSION_EVENT, V$SESSION_WAIT
und V$EVENT_NAME. Diese Views sind zwar für eine Performance-Analyse unerlässlich, ersetzen aber nicht die anderen Informationen, die von der Datenbank zur Verfügung
gestellt werden. Diese Views sollten als Ergänzung verstanden werden. Ich verstehe unter
Wait Interface genau wie [Millsap 2003] alle Timing-Informationen, die uns von der Datenbank zur Verfügung gestellt werden. Im konkreten Fall liefert zwar immer der 10046
Level 12 Trace die meisten (und besten) Informationen, aber auch der Zugriff über verschiedene V$-Views liefert wertvolle Hinweise.
Beginnen wir also historisch, schauen wir uns die Ratios im Detail an. Dabei ist der Ansatz
der, dass bestimmte Verhältnisse von Kennzahlen in der Datenbank einen möglichst guten
Überblick über die Performanz und Hinweise, welcher Bereich zu tunen ist, geben sollen.
Viele dieser Kennzahlen beruhen auf den so genannten dynamischen Performance-Views
oder V$-Views. Die werden V$-Views genannt, weil ihr Name jeweils mit V$ beginnt,
wie zum Beispiel V$SYSSTAT oder V$WAITSTAT. Die Views werden dynamische Performance-Views genannt, weil sie sich oft auf Performance-Daten beziehen. Im Unterschied zu normalen Views werden V$-Views bei jedem Neustart der Datenbank neu initialisiert. Diese Views sind erst mal nur SYS zugänglich. Sie sehen zwar aus wie normale
Views, es sind aber interne Strukturen, die nur selektiert und nicht verändert werden können. Es gibt sehr viele V$-Views, ihre Namen finden Sie in der View V$FIXED_TABLE.
Wie Sie hier sehen, sind es in der Version 10.2 fast 400 V$-Views:
SQL> select count(*) from v$fixed_table where name like 'V%' ;
COUNT(*)
---------396
Die V$-Views beinhalten alle möglichen Werte und Kennzahlen, wir konzentrieren uns
aber hier nur auf einige ausgewählte. V$-Views gibt es in zwei Varianten: die V$-View
enthält die Werte der lokalen Datenbank, die GV$-View die Werte aller Datenbanken in
einer RAC-Umgebung; die GV$-Views haben eine zusätzliche Spalte, die die aktuelle Datenbankinstanz anzeigt..
3.2
Statistische Kennzahlen
Viele Kennzahlen, auf denen die Ratios basieren, finden wir in V$-Views. Manche Ratios
müssen wir zwar berechnen, manche werden aber gleich ausgewiesen. In Oracle 10g sehen
Sie alle mehr oder weniger direkt. Fangen wir zuerst mit V$SYSSTAT beziehungsweise
V$SESSTAT an. V$SYSSTAT ist die Summierung aller Werte in V$SESSTAT, also für alle Sessions. V$SESSTAT liefert statistische Kennzahlen pro Session und ist nur für die jeweilige Session dann auch gültig. Verabschiedet sich also die Session aus der Datenbank,
96
3.2 Statistische Kennzahlen
verschwinden auch die Einträge aus V$SESSTAT. In V$SESSTAT haben Sie nur die Spalte
Statistic#, dort müssen Sie mit V$STATNAME joinen, um den Namen der statistischen
Kennzahl zu erhalten. Es gibt auch noch V$MYSTAT für die eigene Session, da funktioniert
es genauso. Demgegenüber ist in V$SYSSTAT bereits der Name der Statistik enthalten.
Es ist ein bisschen unglücklich, dass hier auch genau wie bei den Optimizer-Statistiken,
die wir im letzten Kapitel besprochen haben, der gleiche Ausdruck verwendet wird, obwohl es sich um zwei völlig verschiedene Dinge handelt. Die Statistiken, die wir hier besprechen, sind etwas ganz anders als die Tabellen- und Indexstatistiken, die wir bereits
kennen gelernt haben. Wenn also von Statistiken die Rede ist, müssen Sie immer auf den
Zusammenhang achten, damit Sie wissen, um welche Art von Statistiken es sich handelt.
Hier könnte man statt Statistik auch den Begriff Kennzahl verwenden. Es gibt insgesamt
rund 250 unterschiedliche Kennzahlen, die noch in verschiedene Klassen unterteilt sind,
zum Beispiel sind Statistiken in Klasse 32 nur für Parallel Server/RAC interessant. Die
Statistiken in V$SYSSTAT bilden ein eigenes Kapitel im Anhang von [OraRef 2005]. Dabei sind die wichtigsten Kennzahlen:
Tabelle 3.1 Wichtige Kennzahlen in V$SYSSTAT/V$SESSTAT
Name
Bedeutung
consistent gets
Wie oft wurden Blöcke im Consistent Read (=CR) Modus benötigt?
Details siehe unten.
consistent changes
Wie oft musste ein Benutzerprozess Rollback/Undo für ein CR applizieren? Dieser Wert sollte sehr viel kleiner sein als consistent gets. Details
siehe unten.
db block changes
Ähnlich wie consistent changes. Zähler für die Anzahl Änderungen,
die für ein UPDATE/DELETE notwendig waren.
db block gets
Wie oft wurden Blöcke im CURRENT Modus benötigt? CURRENT
Blöcke braucht es eventuell beim UPDATE.
(db block gets +
consistent gets)
= Logical Reads. Eine der wichtigsten Größen. Wenn Sie 1000000
Logical Reads für 10 Rows brauchen, ist ein Blick auf das verursachende SQL sehr angebracht.
execute count
Summe der SQL-Aufrufe (auch rekursive). In einem OLTP System
sollte Execute Count wesentlich höher sein als Parse Count. In Data
Warehouses und bei AdHoc-Abfragen ist das Parsen in aller Regel vernachlässigbar.
opened cursors
cumulative
Wird für die Bestimmung von Ratios verwendet.
parse count (hard)
Es gibt hard/harte (wirkliche) und soft/weiche Parse-Aufrufe. Bei einem
weichen Parse wird nur noch mal die Autorisierung überprüft, der SQL
Execution Plan ist bereits im Hauptspeicher. Demgegenüber muss bei
einem harten Aufruf der Ausführungsplan des SQL erst aufgebaut werden – das ist eine sehr aufwändige Operation.
parse count (total)
Alle Parse-Aufrufe (hard und soft).
97
3 Das ABC des Tuning
98
Name
Bedeutung
parse time CPU
Nur wenn TIMED_STATISTICS gesetzt ist. CPU-Zeit (in Zehntel Millisekunden) für alle Parse-Aufrufe.
Parse time elapsed
Nur wenn TIMED_STATISTICS gesetzt ist. Insgesamt verstrichene Zeit
(in Zehntel Millisekunden). Wenn Sie Parse Time CPU hiervon abziehen, sehen Sie, wie lange Sie beim Parsen auf Ressourcen warten.
physical reads
Anzahl Blöcke, die gelesen wurden (von Festplatte plus Direct Reads).
physical reads direct
Direct Reads werden direkt eingelesen, der Buffer Cache wird hierbei
umgangen. Direct Reads kommen bei Sortieroperationen vor, wenn Sie
Parallel Query verwenden, oder beim Einsatz des Direct-Path API (z.B.
SQL*Loader mit der Option DIRECT oder Direct-Path INSERT).
physical writes
Anzahl Blöcke, die geschrieben wurden (von Festplatte plus Direct
Writes).
physical writes direct
Direct Writes werden, ohne durch den Buffer Cache zu gehen, direkt
runtergeschrieben. Wie bei Direct Reads kommen Direct Writes bei
Sortieroperationen vor, wenn Sie Parallel Query verwenden oder beim
Einsatz des Direct-Path API (z.B. SQL*Loader mit der Option DIRECT
oder Direct-Path Export).
redo log space requests
Dieser Zähler geht hoch, wenn das aktive Redo Log voll ist und Oracle
warten muss, bis der Log Switch erfolgt ist. Redo Logs vergrößern.
redo size
Summe Redo in Byte.
recursive calls
Anzahl Recursive Calls. Recursive Calls sind Zugriffe auf das Data Dictionary, die von Oracle selbst generiert werden. Beim Einsatz von
PL/SQL geht der Zähler ebenfalls hoch.
SQL*Net roundtrips
to/from client
Wichtig beim SQL*Net Tuning. Wie oft erfolgte die Kommunikation
zwischen Client-Programm und Server?
SQL*Net roundtrips
to/from dblink
Wichtig beim SQL*Net Tuning, vor allem für Materialized Views.
Wie oft erfolgte die Kommunikation zwischen Datenbank und Datenbank-Link(s)?
session logical reads
Summe DB Block Gets + Consistent Gets
sorts (disk)
Wie viele Sorts mussten auf Disk ausgeführt werden? Sollte möglichst
klein sein, eventuell SORT_AREA_SIZE erhöhen.
sorts (memory)
Anzahl Sorts, die im Memory erfolgten. Besser als im Memory geht
nicht.
sorts (rows)
Anzahl Rows, die insgesamt sortiert wurden.
table fetch by rowid
Anzahl Tabellenzugriffe über Rowid, normalerweise bedeutet das
über Index und ist das, was man will.
table fetch continued
row
Anzahl Tabellenzugriffe für Chained/Migrated Rows. Chained/Migrated
Rows sind normal, wenn Sie Datentypen haben (LONG/LOB), bei
denen ein einzelner Wert größer sein kann als ein Oracle Block.
Falls das nicht der Fall ist, sollte die Tabelle mit besseren Werten für
PCTFREE/PCTUSED reorganisiert werden. Manchmal reicht auch
schon ein einfacher Export/Import der Tabelle.
3.2 Statistische Kennzahlen
Name
Bedeutung
table scan blocks gotten
Anzahl Blöcke, die während des sequenziellen Zugriffes auf die Rows
einer Tabelle abgesucht wurden. Mit consistent gets abgleichen.
table scan rows gotten
Anzahl Rows der Table Scans.
table scans
(cache partitions)
Table Scans für Tabellen, die CACHE gesetzt haben.
table scans
(Direct Reads)
Anzahl Table Scans über Direct Reads.
table scans (long tables)
Full Table Scans.
table scans
(short tables)
Short Tables sind Tabellen, die kleiner sind als 5 Blöcke (Oracle 7)
oder CACHE gesetzt haben. In Oracle 10 hat sich dies geändert, dort
werden Tabellen, die kleiner sind als 20 Blöcke, automatisch im Hauptspeicher gecached.
user calls
Anzahl User Calls total, dazu zählen Login, Parse, Execute, Fetch etc.
user commits
Anzahl COMMITs. Das kommt am ehesten einer Transaktionsrate
nahe.
user rollbacks
Anzahl ROLLBACKs. Wenn Sie hier im Vergleich zu den COMMITs eine hohe Zahl sehen, fragen Sie mal die Applikation, was sie da
eigentlich macht.
Um die Bedeutung der Kennzahlen 'consistent reads' und 'consistent gets' zu verstehen,
sollten Sie sich mit Multi-Versioning in Oracle vertraut machen. Die Details zum MultiVersioning finden Sie in [OraCon 2005] im Kapitel über Data Concurreny und Consistency, hier die Kurzfassung: Wenn Sie Daten lesen in Oracle, werden diese Daten nie gesperrt. Nun ja, das klingt zuerst einmal nicht so spannend. Das Wörtchen nie ist hier ausschlaggebend. Die Daten werden also auch nicht – für den lesenden Prozess! – gesperrt,
wenn sie während der Laufzeit der Abfrage irgendwie verändert werden.
Nehmen wir mal an, Benutzer Hans startet um 16:30 eine langdauernde Abfrage auf Tabelle A, die immer etwa 5 Minuten benötigt. Genau eine Minute später um 16:31, die Abfrage
von Hans läuft also bereits seit einer Minute, verändert Benutzer Hugo über ein UPDATE
alle Daten in der Tabelle A, also sowohl Daten, die Hans bereits gelesen hat als auch Daten, die er gleich lesen wird.
Was passiert in diesem Fall mit der Abfrage von Hans? Gar nichts passiert, Hans kriegt die
Tabellendaten korrekt zurück.
Korrekt bedeutet hier, dass Hans um 16:35 die Daten so sieht, wie sie waren, als er die Abfrage um 16:30 startete, also ohne Hugos nachträgliche Änderungen. Diese wirkten sich
zwar auch auf die Daten, die Hans bereits gelesen hatte, aus, aber das ja erst nachträglich.
Der Benutzer erhält also immer eine konsistente Sicht der Daten.
Möglich wird dies durch Multi-Versioning. Multi-Versioning bedeutet, es können mehrere
Versionen eines Blockes existieren. Als Hans seine Abfrage startete, geschah dies mit einer bestimmten SCN. SCN bedeutet heutzutage System Change Number, das können Sie
99
3 Das ABC des Tuning
sich als internen Zeitstempel vorstellen. Früher wurde SCN auch als Abkürzung für System Commit Number verstanden; das sehen Sie in der Version 10.2 auch noch, wenn Sie
beispielsweise einmal (unter Unix) den Befehl: oerr ora 8209 ausführen:
Error: ORA 8209
Text:
scngrs: SCN not yet initialized
---------------------------------------------------------------------------Cause: The System Commit Number has not yet been initialized.
Action: Contact your customer support representative.
System Change Number ist aber die bessere Bezeichnung, da sie einen auch nicht so leicht
zu der Annahme verleitet, es kann nur eine solche Nummer geben; es gibt verschiedene
SCNs, aber das nur am Rande.
Jeder Block in Oracle enthält auch die SCN. Jede Transaktion startet zu einer bestimmten
Zeit. Auch rein lesende Abfragen wissen, mit welcher SCN sie ihre Abfragen starteten. Als
Hugo sein UPDATE absetzte, protokollierte Oracle zuerst den aktuellen Stand im Rollback/Undo Tablespace. Nehmen wir mal an Hugo veränderte Daten in den Blöcken 800
und 801. Im Rollback/Undo wurden also die alten Werte der betroffenen Zeilen dieser
Blöcke zusammen mit der betreffenden SCN des UPDATE protokolliert. Wenn jetzt die
Abfrage die Blöcke 800 und 801 liest, sieht sie, dass die Werte mittlerweile verändert wurden, weil die SCNs in diesen Blöcken neuer sind als die SCN der Abfrage. Die Abfrage
geht nun in den Rollback/Undo Tablespace und liest dort die alten Werte für die Blöcke
800 und 801. Anschließend liest sie weiter aus der Tabelle. Trifft sie wieder auf veränderte
Daten, wird der alte Stand wieder aus dem Rollback/Undo Tablespace rekonstruiert. Unter
Umständen kann das bedeuten, das über mehrere Versionen zurückgegangen werden muss.
Oracle garantiert immer einen konsistenten Zustand auf Anweisungsebene. Deshalb spricht
man hier auch von Lesekonsistenz. Gerade bei langdauernden Abfragen auf Tabellen, die
häufig modifiziert werden, sehen Sie also bei den Statistiken 'consistent reads' und 'consistent gets' hohe Werte.
Die für den Festplatten-I/O wichtigen Kennzahlen finden Sie auf Session-Ebene in
V$SESS_IO. Dort finden Sie für jede Session BLOCK_GETS, CONSISTENT_GETS,
PHYSCIAL_READS, BLOCK_CHANGES und CONSISTENT_CHANGES.
Falls Sie Probleme beim Sortieren haben, könnte auch ein Blick auf V$SORT_SEGMENT
und V$SORT_USAGE hilfreich sein. In Oracle 10g stehen hierfür V$TEMPSTAT und
V$TEMPSEG_USAGE zur Verfügung.
Seit Oracle 9.2 können Sie sich Statistiken auf Segmentebene in V$SEGSTAT anzeigen
lassen. Das ist sehr nützlich während der Untersuchung „heißer“ Blöcke, auf die oft zugegriffen wird. Der Parameter STATISTICS_LEVEL muss auf TYPICAL stehen, sonst wird
V$SEGSTAT nicht aktualisiert. Da V$SEGSTAT nur Informationen über das Segment bereitstellt, müssen Sie mit DBA_OBJECTS joinen, falls Sie auf Benutzerebene Untersuchungen durchführen wollen.
In der folgenden Abfrage schauen wir uns das mal für den Benutzer SCOTT an:
SQL> select object_name,STATISTIC_NAME,value from v$segstat, dba_objects
where object_id=DATAOBJ#
2* and value > 0 and owner='SCOTT' order by 3,2,1;
100
3.2 Statistische Kennzahlen
OBJECT_NAME
STATISTIC_NAME
VALUE
---------------------------------------- -------------------------------PK_DEPT
physical reads
1
PK_DEPT
physical reads
16
PK_DEPT
logical reads
16
PK_EMP
logical reads
16
Für das I/O ist V$FILESTAT die View der Wahl. Dort werden gibt esauch Zeiten angezeigt, aber wieder nur, wenn TIMED_STATISTICS gesetzt ist. Beachten Sie bitte, dass
Sie hier jeweils als Werte die Anzahl Reads/Writes und die Anzahl der gelesenen/geschriebenen Blöcke haben. Hier erwarten Sie zwischen diesen Werten normalerweise Differenzen, weil Sie ja Multiblock I/O sehen möchten. Je nach Disk-Subsystem, das Sie verwenden, sind die Werte hier natürlich mehr oder weniger nützlich. Falls Sie ein fortgeschrittenes Disksystem wie EMC oder Hitachi verwenden, sind die Werte hier nicht mehr
aussagekräftig, da diese Systeme noch eine zusätzliche Abstraktionsschicht zwischen Dateisystem und physikalischer Disk einbringen. Das hat dann wiederum den Nebeneffekt,
dass V$FILESTAT nichts mehr aussagt. Falls Sie RAID verwenden, haben Sie das gleiche
Problem, da Sie hier ja nicht das I/O per Stripe sehen. Allerdings gibt es seit Oracle 9.2 ein
Oracle-Feature, das I/O Topology heißt. Damit bekommen Sie zumindest für EMC Symmetrix-Systeme wieder aussagekräftige Daten. Falls Sie aber die Zuordnung von Dateien
auf Volumes/Plexes etc. treffen können, ist in 10g die Auswertung über DBA_HIST_FILESTATXS und ein entsprechendes SUBSTR() auf FILENAME immer noch sinnvoll, hier
mal ein kleines Beispiel:
select
Reads",
"Blöcke
"Waits"
substr(filename,8,50) Datei, tsname Tablespace, phyrds "Anzahl
phyblkrd "Blöcke Reads",phywrts "Anzahl Writes", phyblkwrt
Writes",readtim "Read Time", writetim "Write Time",wait_count
from dba_hist_filestatxs order by 7,8,9;
Wichtige Kennzahlen für die Auslastung des Shared Pool finden Sie in V$ROWCACHE
(Dictionary Cache), V$LIBRARYCACHE und V$SGASTAT; in Oracle 10g ist dann noch
V$SGAINFO interessant. V$SHARED_POOL_ADVICE zeigt mögliche Verbesserungen
für kleinere oder größere Größen des Shared Pool im Bereich zwischen 10 und 200 Prozent
der aktuellen Werte an. V$SHARED_POOL_RESERVED schließlich liefert Ihnen teilweise
auch Informationen, wenn der Parameter SHARED_POOL_RESERVED_SIZE nicht gesetzt
ist. In diesem Fall werden in Version 10.2 dann fünf Prozent von SHARED_POOL_SIZE
genommen. ist Vor allem für die Analyse des Fehlers ORA-4031, der vorzugsweise überhaupt nicht auftreten sollte, kann dieser View mit Einschränkungen hilfreich sein; bei Post
Mortem-Analysen nützt er Ihnen nichts.
Statistiken verdichten
Oracle 10g schließlich führte noch weitere Möglichkeiten für die Verdichtung von Statistiken ein. Mit dem DBMS_MONITOR Package können Sie Statistiken auf verschiedenen
Ebenen aktivieren: für einen bestimmten Client, für einen bestimmten Service, ein Modul
oder auf Aktionsebene. Die Aktivierung erfolgt am besten in einem ON-LOGON Trigger.
Hier ein Beispiel, das Benutzernamen, SID und IP-Adresse des Clients als Bausteine für
den Identifier verwendet:
101
3 Das ABC des Tuning
CREATE OR REPLACE TRIGGER On_Logon_SCOTT
AFTER LOGON ON SCOTT.Schema
DECLARE
v_addr VARCHAR2(11);
v_sid varchar2(10);
my_id VARCHAR2(70);
BEGIN
select ora_login_user into my_id from dual;
select to_char(sid) into v_sid from v$mystat where rownum=1;
v_addr := ora_client_ip_address;
my_id:=my_id||' '||v_addr||' '||v_sid;
DBMS_SESSION.SET_IDENTIFIER(my_id);
DBMS_MONITOR.CLIENT_ID_STAT_ENABLE(my_id);
END;
/
Die Statistiken für den Client werden dann im View V$CLIENT_STATS protokolliert. Für
die Aktivierung auf Service-, Modul- oder Aktionsebene verwenden Sie DBMS_MONITOR.SERV_MOD_ACT_STAT_ENABLE. Service ist hier der/ein Name, wie er im Parameter SERVICE_NAMES gesetzt ist. Ein Servicename kann aber auch über ALTER
SYSTEM oder das DBMS_SERVICE Package gesetzt werden.
Modul und Aktion können Sie auch in älteren Versionen verwenden, sie werden über die
Prozeduren SET_MODULE... und SET_ACTION... im Package DBMS_APPLICATION_
INFO gesetzt. DBMS_APPLICATION_INFO war bereits in Oracle 8i verfügbar. Die verdichteten Statistiken sehen Sie dann in V$SERVICE_STATS beziehungsweise V$SERV_
MOD_ACT_STATS.
3.3
V$WAITSTAT
Hier sehen Sie nur Werte, wenn TIMED_STATSITICS gesetzt ist. In diesem View sehen
Sie Waits pro Blockklasse. Wenn der Zähler (COUNT) nicht hochgeht, haben Sie auch
keine Waits auf dieser Klasse (und kein Problem). In der Tabelle auf der nächsten Seite
habe ich ein paar erste Ratschläge gesammelt. Bitte beachten Sie, dass in Abhängigkeit
vom Oracle Release nicht alle Klassen vorhanden sind. Wenn mehrere Ratschläge vorhanden sind, kann es sein, dass mehrere Aktionen von Nöten sind (muss aber nicht sein) oder
auch eine der aufgelisteten eventuell schon ausreichend ist.
Tabelle 3.2 Empfehlungen für Werte in V$WAITSTAT
Klasse
Ratschlag
bitmap block
bitmap index block
Nur bei Locally Managed Tablespaces. DB_BLOCK_BUFFERS
erhöhen. I/O beschleunigen (Disks/Controller/Stripe Größen).
data block
FREELISTS (dynamisch seit 8.1.6) erhöhen. Hot Blocks in der Datenbank eliminieren. Unselektive Indizes? Anpassen von PCTFREE/
PCTUSED. Anzahl Rows pro Block reduzieren. INITRANS erhöhen.
extent map
102
3.4 Ratios
Klasse
Ratschlag
file header block
free list
Taucht typischerweise nur bei Oracle Parallel Server auf. FREELIST
GROUPS erhöhen (erfordert Neuanlegen der Tabelle).
save undo block
Nur bei OFFLINE Rollback/Undo
save undo header
dito
segment header
FREELISTS erhöhen oder Größe der Extents zu klein
sort block
SORT_AREA_SIZE/Temporary Tablespace
system undo block
Rollback Segment SYSTEM zu klein
undo block
Zu kleine Rollback Segments/Undo
undo header
Zu wenige Rollback Segments/Undo
unused
Nur bei Locally Managed Tablespaces, bezeichnet Space HeaderBlöcke. DB_BLOCK_BUFFERS erhöhen. I/O beschleunigen
(Disks/Controller/Stripe Grössen).
1st level bmb
Nur bei Locally Managed Tablespaces
nd
Nur bei Locally Managed Tablespaces
rd
Nur bei Locally Managed Tablespaces
2 level bmb
3 level bmb
3.4
Ratios
Nachdem wir jetzt die ganzen Statistiken kennen gelernt haben, sollten die folgenden Ratios kein Problem mehr sein. Fangen wir mit der bekanntesten aller Ratios an, der Buffer
Cache Hit Ratio, manchmal auch nur kurz Hit Ratio genannt. Dieses Verhältnis zeigt an,
wie oft Prozesse, die auf einen bestimmten Block zugreifen, diesen Block im Buffer Cache
finden. Ist der Block bereits im Buffer Cache, ist er ja schon im Hauptspeicher. Das klingt
ja erst mal gut. Es gibt verschiedene Formeln für diese Ratio, die einfachste ist:
Buffer Cache Hit Ratio = 1 - ( physical reads )
-------------------------------------( consistent gets + db block gets )
Statt Consistent Gets + DB Block Gets wird manchmal auch von logical reads gesprochen,
das haben wir ja oben schon bei den Kennzahlen gesehen.
Die Hit Ratio wird oft prozentual ausgedrückt, also das Ergebnis der obigen Formel mit
100 multipliziert. Allerdings änderte Oracle in 7.3.4 die Definition von Physical Reads, die
seitdem auch Direct Block Reads einschließen. Somit gibt die obige Formal nur eine Untergrenze. Eine bessere Formel zieht das in Betracht:
Hit ratio = 1 (physical reads -(physical reads direct + physical reads direct (lob)))
------------------------------------------------------------------------(db block gets + consistent gets -(physical reads direct + physical reads direct (lob)))
103
3 Das ABC des Tuning
Falls Sie Buffer Pools verwenden, sollten Sie die Ratio pro Buffer Pool berechnen, das erfolgt dann über V$BUFFER_POOL_STATISTICS . Gelegentlich sieht man auch die Miss
Ratio erwähnt, das ist dann einfach 100 – Hit Ratio in %. Die Hit Ratio sollte möglichst
hoch sein, Werte über 80 werden allgemein als gut angesehen. Allerdings hauptsächlich in
OLTP-Applikationen, in Data Warehouses sind oft keine guten Hit Ratios zu erwarten.
Aber auch eine100%ige Hit Ratio garantiert keine gute Performanz. Die meisten Troubleshooting-Einsätze, die ich bisher durchführte, fanden alle auf Datenbanken statt, die exzellente Hit Ratios hatten. Denn 100% Hit Ratio können Sie z.B. auch bekommen, wenn ein
sehr unselektiver Index häufig benutzt wird. Dann sind jede Menge Blöcke im Cache, die
immer wieder abgesucht werden, aber die Performanz ist schlecht für die meisten Abfragen. Beim Einsatz von Parallel Query kann die Hit Ratio auch drastisch runtergehen (wegen der Direct Reads).
Weiter gibt es einige Ratios für die Auslastung des Shared Pool. Fangen wir mit der Dictionary Cache Hit Ratio an. Die ermitteln wir in V$ROWCACHE:
Dictionary Cache Hit Ratio = 1 - sum ( gets )
----------------------------------sum ( getmisses )
Das Verhältnis kann natürlich auch prozentual ausgedrückt werden. Diese Ratio sollte höher als 90 Prozent sein. Die Parameter, die Sie in V$ROWCACHE sehen, waren in Oracle
Version 6 noch eigenständige init.ora/spfile-Parameter. Seit Oracle 7 wird das aber alles
über SHARED_POOL_SIZE konfiguriert.
Eine weitere Ratio hier ist die Library Cache Hit Ratio. Die wird ermittelt über
V$LIBRARYCACHE und sollte kleiner als 1% (< .1) sein :
Library Cache Hit Ratio = sum( reloads )
----------------------------------sum( pins )
Auch hier besteht die Kur im Erhöhen des Parameters SHARED_POOL_SIZE. Hit und
Pin Ratio im Library Cache sollten (pro Namespace) über 70% sein:
Library Hit Ratio = trunc(gethitratio * 100)
Library Pin Ratio = trunc(pinhitratio * 100)
Auch hier gilt gegebenenfalls SHARED_POOL_SIZE erhöhen bzw. ab 10g SGA_TARGET und/oder SGA_MAX_SIZE.
Ein weiteres wichtiges Verhältnis ist die Parse Ratio, also wie viele Statements aus allen
SQL-Anweisungen vor der Ausführung erst noch geparsed – also quasi in Oracle übersetzt
– werden müssen:
Parse Ratio = sum ( parse count )
----------------------------------------sum ( opened cursors cumulative )
Die Parse Ratio sollte auf OLTP-Systemen sehr klein sein (< 1,5 Prozent). Falls viel AdHoc SQL und dynamisches SQL verwendet wird, ist die Parse Ratio natürlich sehr hoch.
Hohe Parse Ratios bei OLTP-Systemen sind ein Indikator, dass die Applikation nicht mit
104
3.5 Wait Events
Bind-Variablen arbeitet. Falls Oracle Forms verwendet wird, besteht dort noch Optimierungspotential.
Interessant ist schließlich noch die Recursive Call Ratio. Recursive Calls sind Abfragen
auf das Data Dictionary, die von Oracle intern generiert werden:
Recursive Call Ratio = sum ( recursive calls )
----------------------------------------sum ( opened cursors cumulative )
Die Recursive Call Ratio sollte normalerweise kleiner als 10 sein (auf Produktionssystemen) und kleiner als 15 auf Entwicklungssystemen. Wenn Sie hier hohe Zahlen haben,
wechseln Sie zu Locally Managed Tablespaces.
Das sind die wichtigsten Ratios, damit sollten Sie sich bereits einen guten Überblick über
ein System verschaffen können.
In Oracle 10g werden diese und andere Ratios automatisch jede Minute berechnet. Voraussetzung ist wieder STATISTICS_LEVEL auf TYPICAL oder ALL. In V$METRICNAME
sehen Sie, welche Metriken Oracle berechnet. Die Metriken werden dabei in verschiedene
Gruppen unterteilt, was hilfreich ist. Die meisten Metriken verteilen sich aber auf nur zwei
Gruppen: langdauernde Transaktionen (System Metrics Long Duration) und kurze Transaktionen (System Metrics Short Duration). In Oracle 10.1.0.3 habe ich zum Beispiel 184
Metriken gezählt!
3.5
Wait Events
Noch zu Lebzeiten von Oracle 6 (ich glaube, es war für Parallel Server mit 6.0.30, aber da
bin ich mir nicht mehr) führte Oracle die so genannten Wait Events ein. Die wurden seitdem fleißig ausgebaut, allein zwischen Oracle 9.2 und Oracle 10 kamen noch ein paar
Hundert dazu. Wenn Sie in Oracle 10.2.0.1 ein SELECT COUNT(*) FROM V$EVENT_
NAME absetzen, kommt als Ergebnis 872 zurück. Das ist eine beeindruckende Zahl, aber
in der Praxis sehen Sie längst nicht alle. Die Wait Events erlauben es einem, im laufenden
Betrieb zu sehen, auf was und wie lange eine Session wartet. Das ist natürlich eine ganz
feine Sache, erlaubt es einem doch, im laufenden Betrieb nachzusehen, wo den Patienten
denn der Schuh nun wirklich drückt. Diese Wait Events können in einigen V$ nachgesehen
werden, als da sind:
V$SESSION_WAIT. Hier sehen Sie Sessions, die gerade warten oder gewartet haben.
V$SESSION_EVENT. Hier sehen Sie alle Wait Events, summiert für jede Session.
V$SYSTEM_EVENT. Hier sehen Sie alle Wait Events, summiert über alle Sessions.
Dieser View ist nützlich, wenn Sie sich zuerst einen allgemeinen Überblick über das
System verschaffen müssen.
Wie bereits erwähnt, sind die Namen der Events aus V$EVENT_NAME ersichtlich. Wichtig ist hier wieder, dass der Parameter TIMED_STATISTICS auf TRUE gesetzt ist. In Oracle 10g ist das automatisch der Fall, sofern der Parameter STATISTICS_LEVEL auf
105
3 Das ABC des Tuning
TYPICAL oder ALL gesetzt ist. TYPICAL ist voreingestellt. TIMED_STATISTICS kann
aber auch dynamisch genau wie STATISTICS_LEVEL über ALTER SESSION gesetzt
werden. Die Struktur der Wait-Tabellen sehen wir uns zuerst anhand des Views V$SESSION_EVENT an:
SQL> desc v$session_event
Name
Null?
----------------------------------------- -------SID
EVENT
TOTAL_WAITS
TOTAL_TIMEOUTS
TIME_WAITED
AVERAGE_WAIT
MAX_WAIT
TIME_WAITED_MICRO
Typ
-------------------NUMBER
VARCHAR2(64)
NUMBER
NUMBER
NUMBER
NUMBER
NUMBER
NUMBER
Das ist jetzt von einer 9.2 Installation; in 8.1.7 gab es die Spalte TIME_WAITED_MICRO
(zeigt die gewartete Zeit in Mikrosekunden an) noch nicht. In Oracle 10g kommt hier noch
die Spalte EVENT_ID hinzu, was aber nicht so wichtig ist. Wichtig ist vielmehr, wie viel
(TOTAL_WAITS) und wie lange (TIME_WAITED) die Session auf welches Event gewartet hat. Wie gesagt, es gibt Hunderte von Events, aber nur einige von ihnen sind wirklich wichtig. Ignorieren können Sie im Normalfall diese Events, die oft auch als Idle
Events bezeichnet werden:
rdbms ipc message
rdbms ipc message block
rdbms ipc reply
SQL*Net break/reset to client
SQL*Net break/reset to dblink
SQL*Net message from client
SQL*Net message from dblink
SQL*Net message to client
SQL*Net message to dblink
SQL*Net more data from client
SQL*Net more data from dblink
SQL*Net more data to client
SQL*Net more data to dblink
Das bedeutet aber nicht, das nicht auch diese Events wichtig sein können, es kommt immer
auf den Zusammenhang an. Millsap beispielsweise bringt in Case 3 in [Millsap 2003] ein
schönes Beispiel, in dem das Event „SQL*Net Message from client“ den Großteil der
Wait-Zeit ausmacht und den Ausgangspunkt der Untersuchung bildet.
Die rdbms-Messages beziehen sich alle auf Oracle-interne Kommunikation und die
SQL*Net Messages auf die Kommunikation zwischen Oracle-Server und dem ClientProgramm. Diese Kommunikation können Sie teilweise beschleunigen, das wurde bereits in
Kapitel 1 besprochen. Es ist ein bisschen verwirrend, dass hier immer SQL*Net steht, auch
106
3.5 Wait Events
wenn Sie nur lokal auf den Server zugreifen. Hintergrund hier ist die Oracle-Architektur,
in welcher der Serverprozess vom Client getrennt ist. Früher konnte man noch auf manchen Betriebssystemen Programme mit der Option Singletask linken, dann waren OracleServer- und Client-Programm in einem Executable zusammengelinked. Es gibt dafür auch
ein Wait Event, das ist „single-task Message“. Das Singletask-Programm war sehr schnell,
da ja der ganze Kommunikationsoverhead drastisch reduziert war. Es war aber auch sehr
gefährlich, weshalb Oracle es dann später verboten hat. Was geblieben ist, sind die Namen
im Wait Interface. Je nach Installation sehen Sie auch die einen Events und die anderen
nicht. So gibt es beispielsweise jede Menge Events, die mit „global cache“, „ges“ oder
„gcs“ beginnen. Diese Events gibt es aber nur im Parallel Server/RAC-Umfeld. Wenn Sie
also eine normale Datenbank fahren, sehen Sie die nicht. Daneben gibt es einige Events,
die auf Probleme mit speziellen Prozessen/Bereichen hinweisen. Die folgende Liste zeigt
einige ausgewählte Namensmuster für Gruppen von Events aus der Oracle 10g. Dies sind
auch Events, die sich über init.ora/spfile-Parameter zumindest teilweise tunen lassen und
die generell mit der Konfiguration der Datenbank zusammenhängen. So gibt es allein für
den Archiver in 10g 25 Events. Die Spalte WAIT_CLASS in V$EVENT_NAME verrät
Ihnen noch, in welche Wait-Klasse das jeweilige Event fällt. In Version 10.2 existieren dafür 12 verschiedene Kategorien:
SQL>
1
2
3
4*
r
select wait_class#, wait_class, count(event#) anzahl
from v$event_name
group by wait_class#, wait_class
order by 1,2
WAIT_CLASS#
----------0
1
2
3
4
5
6
7
8
9
10
11
WAIT_CLASS
ANZAHL
------------------------------ ------Other
588
Application
12
Configuration
23
Administrative
46
Concurrency
24
Commit
1
Idle
62
Network
26
User I/O
17
System I/O
24
Scheduler
2
Cluster
47
Die Wait Events sind im Anhang der Oracle Reference [OraRef 2005] aufgeführt, teilweise
mit weiteren Hinweisen:
Tabelle 3.3 Wichtige Wait Event-Gruppen für das Tuning der Datenbank
Bereich/Kategorie
Namensmuster
Anzahl Events/Kategorie
Versionen: 10.1/10.2
Archiver
ARCH%
25/24
Backup
(vor Oracle 10g sehen Sie hier nur sbt…)
Backup: sbt%
28/28
Redo Log Writer
LGWR%
10/15
107
3 Das ABC des Tuning
Bereich/Kategorie
Namensmuster
Anzahl Events/Kategorie
Versionen: 10.1/10.2
Log% buffer space
12
Parallel Query
PX%
40/40
DataGuard/LogMiner
RFS%
11/11
Streams
STREAMS%ge
6/0
SWRF%
2/0
Streams%
2/19
undo%
3/9
Rollback/Undo
Je nach Event existieren noch verschiedene Parameter, die weitere Hinweise geben. Das
sehen Sie dann aber nur in V$SESSION_WAIT. Diese View ändert sich natürlich auch mit
jeder Version. In Version 10.2 sieht sie wie folgt aus:
SQL> desc v$session_wait;
Name
Null?
----------------------- -------SID
SEQ#
EVENT
P1TEXT
P1
P1RAW
P2TEXT
P2
P2RAW
P3TEXT
P3
P3RAW
WAIT_CLASS_ID
WAIT_CLASS#
WAIT_CLASS
WAIT_TIME
SECONDS_IN_WAIT
STATE
Type
---------------NUMBER
NUMBER
VARCHAR2(64)
VARCHAR2(64)
NUMBER
RAW(4)
VARCHAR2(64)
NUMBER
RAW(4)
VARCHAR2(64)
NUMBER
RAW(4)
NUMBER
NUMBER
VARCHAR2(64)
NUMBER
NUMBER
VARCHAR2(19)
SID ist wieder der Session Identifier, der uns ja schon aus V$SESSION bekannt ist. Interessant ist die SEQ# Spalte. Solange eine Session aktiv wartet, sollte SEQ# bei jeder Abfrage erhöht werden. Sie können davon ausgehen, dass spätestens nach drei Sekunden
V$SESSION_WAIT nachgeführt wird. Falls Sie vermuten, dass eine Session hängt, werfen Sie mal einen Blick darauf. Wenn sich SEQ# über ein paar Minuten nicht verändert,
können Sie davon ausgehen, dass die Session wirklich hängt. Die können Sie dann mit
ALTER SYSTEM KILL SESSION abschließen. WAIT_TIME und SECONDS_IN_WAIT
sind natürlich nur gefüllt, falls TIMED_STATISTICS gesetzt ist. Beim STATE sehen Sie
entweder WAITING oder WAITED KNOWN TIME. Wenn Sie dort WAITED UNKNOWN TIME sehen, ist TIMED_STATISTICS nicht gesetzt. Die Parameter P1 bis P3
sind die Parameter, pro Event kann es bis zu drei geben. In den Spalten P1TEXT bis
P3TEXT sehen Sie jeweils, wie der Parameter zu interpretieren ist. Zusätzlich wird für jeden Parameter der numerische Wert und der Wert als RAW dargestellt. Für die praktische
108
3.5 Wait Events
Arbeit interessiert uns aber eigentlich immer nur der numerische Wert. Wie lange eine Session auf das jeweilige Event wartet, ist unterschiedlich, oft sind es 1 oder 3 Sekunden.
Im Folgenden sind einige ausgewählte Events, ihre Bedeutung und die dazugehörigen Parameter beschrieben. Wenn es um applikatorisches Tuning geht, haben Sie es vor allem mit
diesen Events zu tun:
Tabelle 3.4 Wichtige Wait Events für das Tuning der Applikation
Event
Bedeutung
Parameter
Buffer busy waits
Session wartet, bis Block im Buffer Cache frei wird.
Applikation auf Hot Blocks prüfen.
1) File#
Db file parallel
write
Session wartet, bis parallel I/O fertig ist.
1) Files
Db file scattered
read
Wie viel I/O fürs Lesen notwendig ist.
2) Block#
2) Anzahl der Blöcke
1) File#
2) Block#
3) Anzahl der Blöcke
Db file sequential read
Wie viel I/O fürs Lesen notwendig ist. Das ist beim
zufälligen Zugriff (Random Access); die Anzahl der gelesenen Blöcke ist hier also normalerweise immer 1!
1) File#
Db file single
write
Wie viel I/O Zeit fürs Schreiben der File Header
benötigt wird. Es sollten mehrere Blöcke auf einmal
geschrieben werden.
1) File#
2) Block#
2) Block#
3) Anzahl der Blöcke
Direct path read
Session wartet bis maximal 10 Sekunden auf ausstehenden I/O. Direct Path Rreads treten auch beim
Sortieren auf.
Direct path write
Wie oben, nur diesmal fürs Schreiben.
Enqueue
Session wartet auf eine Enqueue. Hier muss weiter untersucht werden, welche Enqueue gehalten wird.
Ist in Oracle 10g sehr ausgebaut worden, dort sehen
Sie gleich, welche Enqueue das Problem verursacht.
1) Name und Modus
Free buffer waits
Session fand erst mal keinen freien Buffer. Eventuell
DB_BLOCK_MAX_DIRTY_TARGET zu hoch.
1) File#
Session wartet bis zu 2 Sekunden auf ein Latch, das
im Moment von einer anderen Session gehalten wird.
Hier muss weiter untersucht werden, welches Latch
gehalten wird. Ist in Oracle 10g ausgebaut worden,
dort sieht man gleich, welches Latch das Problem verursacht.
2) Latch#
Latch free
2) Block#
109
3 Das ABC des Tuning
Mit LATCH# können Sie das dazugehörige Latch aus V$LATCHNAME ermitteln. Latches sind interne Strukturen, mit denen Oracle Ressourcen im Hauptspeicher sperrt und
freigibt. Bei Latches wie „equence cache“ sagt schon oft der Name, wo das Problem liegt,
oft werden Sie aber nicht umhin kommen, dies detaillierter nachzuschlagen. Oracle Metalink (http://metalink.oracle.com) ist dafür die beste Adresse.
Wenn Sie File# und Block# im Event als Parameter haben, können Sie mit dieser Abfrage
(die sieht a bisserl komisch aus, g’hört aber so) das dazugehörige Objekt und seinen Namen ermitteln. Sie müssen die beiden in spitzen Klammern angegebenen Parameter durch
die aktuellen Werte ersetzen:
SELECT SEGMENT_TYPE, SEGMENT_NAME
FROM DBA_EXTENTS
WHERE FILE_ID = <File#>
AND <Block#> BETWEEN BLOCK_ID AND BLOCK_ID + BLOCKS –1;
Falls Sie Parallel Server oder RAC fahren, haben Sie noch den EXT_TO_OBJ View (kann
auch manuell über catparr.sql erzeugt werden). Dort können Sie folgende Abfrage verwenden, die Ihnen das gleiche Ergebnis liefert:
Select name, kind
from ext_to_obj_view
where file# = <file#>
and lowb <= <block#>
and highb >= <block#>;
In Oracle 10g wurde das Wait Interface noch weiter ausgebaut. Es kamen noch
V$ACTIVE_SESSION_HISTORY, V$SESS_TIME_MODEL, V$SYS_TIME_MODEL,
V$SYSTEM_WAIT_CLASS, V$SESSION_WAIT_CLASS, V$EVENT_HISTOGRAM,
V$FILE_HISTOGRAM, außerdem V$TEMP_HISTOGRAM und zusätzliche Views für
die Metriken hinzu.
Aktive Session History ist übrigens genau das, wonach es klingt. Also eine historisierte
Version der View V$SESSION plus zusätzlicher Infomation aus V$SESSION_WAIT..
Folgende Abfrage zeigt Ihnen beispielsweise die SQL-Anweisungen, die eine bestimmte
Session im angegebenen Zeitraum ausgeführt hat, und wie oft die einzelne Anweisung
ausgeführt wurde:
prompt Bitte Start- und Endzeit im Format DD-MON-YY HH24:MI:SS angeben
prompt Beispiel: 16-JUL-06 08:00:00
SELECT
FROM
WHERE
C.SQL_TEXT, B.NAME, COUNT(*), SUM(TIME_WAITED) waittime
V$ACTIVE_SESSION_HISTORY A, V$EVENT_NAME B, V$SQLAREA C
A.SAMPLE_TIME BETWEEN '&Startzeit' AND '&Endzeit' AND
A.EVENT# = B.EVENT# AND A.SESSION_ID= &SID AND A.SQL_ID =
C.SQL_ID
GROUP BY C.SQL_TEXT, B.NAME;
Sehr nützlich sind hier auch die verschiedenen Views, deren Namen mit _TIME_MODEL
endet. Diese liefern die Zeit (in Mikrosekunden) für ausgewählte Statistiken, meistens parse/execute/cpu-Werte. Somit haben Sie auch die Zeiten für ausgewählte Operationen wie
beispielsweise „sql execute elapsed time“ oder „DB time“. Sie können also klar unterscheiden, ob die Zeit in der Session oder in der Datenbank verbraucht wurde. Für einen
groben Überblick über das System bietet sich hier V$SYS_TIME_MODEL an, hier sehen
110
3.5 Wait Events
Sie, in welchen Kategorien die Zeit verbraucht wird. Falls Sie also mal schauen wollen, ob
die Zeit vornehmlich während der Ausführung von SQL oder während der Ausführung von
PL/SQL verbraucht wird, befragen Sie am besten diesen View. Hier mal eine kleines Beispiel, beachten Sie auch, wie hier auf Sekunden gerundet wird:
SQL>
SQL>
SQL>
2
3
col spent_time head "Zeit (Sec)"
col stat_name head "Statistik"
select STAT_NAME, ROUND((VALUE / 1000000),3) spent_time
from
V$SYS_TIME_MODEL
order by 2 DESC;
Statistik
Zeit (Sec)
---------------------------------------------------------------- ---------DB time
1146.968
sql execute elapsed time
1114.172
PL/SQL execution elapsed time
398.292
background elapsed time
337.089
DB CPU
245.914
parse time elapsed
203.916
hard parse elapsed time
189.666
background cpu time
63.652
PL/SQL compilation elapsed time
27.909
connection management call elapsed time
6.241
hard parse (sharing criteria) elapsed time
2.652
repeated bind elapsed time
.873
hard parse (bind mismatch) elapsed time
.484
failed parse elapsed time
.161
sequence load elapsed time
.093
inbound PL/SQL rpc elapsed time
0
Java execution elapsed time
0
RMAN cpu time (backup/restore)
0
failed parse (out of shared memory) elapsed time
0
Dies war jetzt ein Beispiel für eine Abfrage auf Datenbankniveau. Wie man sieht, wurde
der größte Teil der Zeit mit der Ausführung von SQL (=1114.172 Sekunden), alle übrigen
Zeiten sind weitaus kleiner.
Für einen einzelnen Benutzer muss dann V$SESS_TIME_MODEL verwendet werden, die
entsprechende Abfrage könnte etwa so aussehen:
select A.SID, B.USERNAME "Benutzer", A.STAT_NAME,
ROUND((A.VALUE / 1000000),3) spent_time
from
V$SESS_TIME_MODEL A, V$SESSION B
where
A.SID = B.SID and B.SID = &SID
order by 4 DESC;
Es kamen auch noch jede Menge statische Data Dictionary Views, die historische Informationen anzeigen, in der Version 10g mit der AWR-Infrastruktur hinzu. Diese Views machen Schnappschüsse von den verschiedenen V$-Views und fangen alle mit DBA_HIST
an. Die Daten dort haben Sie allerdings nur, wenn STATISTICS_LEVEL mindestens auf
TYPICAL gesetzt ist. Per Default ist das der Fall. Die Views, deren Namen mit _WAIT_
CLASS endet, liefern die Zeiten pro Wait-Klasse, also z.B. „System I/O“, „User I/O“ oder
„Network“. Damit ist eine noch genauere Analyse möglich. Die folgende Abfrage beispielsweise liefert Ihnen die Daten für die aktuellen Benutzer; beachten Sie auch, wie die
Systembenutzer über NOT IN ausgeschlossen werden:
select A.SID "Session ID", B.USERNAME "Benutzer",
A.WAIT_CLASS "Wait-Klasse", A.TOTAL_WAITS "Total der Waits",
A.TIME_WAITED "Wartezeit"
111
3 Das ABC des Tuning
from
where
V$SESSION_WAIT_CLASS A, V$SESSION B
B.SID = A.SID and B.USERNAME IS NOT NULL
and B.USERNAME not in ('SYS','SYSTEM','DBNSMP,'SYSMAN')
order by 1,2,3;
In Oracle 10g werden auch CPU und Hauptspeicherstatistiken standardmäßig gesammelt,
die sehen Sie in V$OSSTAT. Die Einträge in V$OSSTAT fallen aber je nach Betriebssystem unterschiedlich aus.
Die _HISTOGRAM Views liefern Histogramme pro File, Event oder temporärer Datei..
Dabei sind die Intervalle für die Histogramme < 1 ms, < 2 ms, < 4 ms, < 8 ms, ... < 2^21
ms, < 2^22 ms, = 2^22 ms. Hier wie an anderen Stellen ist wieder Voraussetzung, dass die
Parameter STATISTICS_LEVEL und TIMED_STATISTICS gesetzt sind. Die folgende
Abfrage beispielsweise liefert Ihnen die aufsummierten Maxima pro Event mit Ausschluss
der Events, die als Idle klassifiziert sind:
SQL>
2
3
4
5
6
7
select
from
where
EVENT, max(WAIT_TIME_MILLI*WAIT_COUNT) max_wait_time_milli
V$EVENT_HISTOGRAM
EVENT IN (select NAME from
V$EVENT_NAME
where WAIT_CLASS not in ('Idle'))
and
WAIT_COUNT > 0
group by event
order by 2,1;
EVENT
MAX_WAIT_TIME_MILLI
---------------------------------------- ------------------Log archive I/O
1
instance state change
1
latch: object queue header operation
1
latch: cache buffers chains
2
...
SQL*Net message to client
30165
db file scattered read
79872
db file sequential read
192448
47 rows selected
112
Oracle Tuning in der Praxis
Frank Haas
Rezepte und Anleitungen für Datenbankadministratoren und
-entwickler
ISBN 3-446-40725-1
Vorwort
Weitere Informationen oder Bestellungen unter
http://www.hanser.de/3-446-40725-1 sowie im Buchhandel
Vorwort
Es freut mich sehr, dass mein Tuning-Buch in einer zweiten Auflage veröffentlicht wird –
ietet sich mir doch so die Chance, zum einen Fehler und Irrtümer der ersten Auflage zu
korrigieren (und neue zu machen ...), zum andern es somit auch auf den neuesten Stand zu
bringen. Zum Zeitpunkt der Drucklegung der ersten Auflage war ja Oracle Version 10g
noch relativ frisch und Version 10.2 stand noch in den Sternen. Danken möchte ich an dieser Stelle ganz besonders auch all meinen Lesern, die mir mit Kritik und Anregungen halfen.
Das bedeutet jetzt aber nicht, dass es ein vollkommen neues Buch wurde. Tuning ist meiner Meinung nach eine Aufgabe mit zwei wesentlichen Aspekten. Der erste Aspekt ist die
Methodik und die bleibt sich bisher – und hoffentlich auch in Zukunft – meiner Meinung
nach gleich. 10046 Traces und das Wait Interface existieren jetzt schon seit einigen Jahren,
und das sind für mich die Tools der Wahl beim Tuning. Zwar existieren auch andere
Tools, die hier selbstverständlich auch besprochen werden, doch sehe ich diese eher als
unterstützende Hilfsmittel. Wobei der Weg aber schon ganz klar in Richtung GUI – d.h.
also Enterprise Manager etc. – zu führen scheint. Das ist in der Softwareindustrie auch
nicht anders als im Automobilbau, das neueste Modell ist immer schöner und besser. Aber
es gilt immer noch: Wenn Sie einmal das Autofahren gelernt haben, können Sie das. Wenn
Sie sich dann einen neuen Wagen zulegen, müssen Sie zwar ein paar neue Knöpfe und
Schalter kennen lernen, aber wie man fährt, müssen Sie nicht mehr lernen. Das führt uns
gleichzeitig auch zum zweiten Aspekt. Tuning und speziell Oracle-Tuning setzt auch voraus, dass Sie die Mittel kennen, die Ihnen die jeweilige Version zur Verfügung stellt. Auch
diesen Punkt möchte ich an einem Beispiel illustrieren. Es ist schon einige Jahre her und
Oracle Version 8.1 war damals noch relativ frisch, als ich einen Troubleshooting-Einsatz
bei einem Kunden hatte. Es ging dort um eine Börsenapplikation, bei der der Benutzer die
aktuellen Werte von Aktien an verschiedenen Handelsplätzen abfragen konnte. Das erste
Hauptproblem dort war die berühmt-berüchtigte ALL-ALL-Abfrage. Diese Abfrage wurde
so genannt, weil dort alle Aktien – das erste ALL – an allen Handelsplätzen – das zweite
ALL – abgefragt wurden.
Der Kenner erkennt sofort, dass es sich hier offensichtlich um mindestens einen Full Table
Scan handelt, der auch nicht zu vermeiden ist. Fragen des Designs standen – natürlich,
XI
Vorwort
meiner Erfahrung nach wird man immer erst dann geholt, wenn man absolut keinen anderen Ausweg mehr sieht – nicht zur Debatte, es handelte sich um ganz normale einfache
Tabellen, die nicht weiter angetastet werden durften.
Diese Abfrage dauerte nach dem Startup der Datenbank 2 Minuten. Meine Lösung damals
bestand aus zwei Teilen:
1. das Platzieren der Tabellen in den KEEP Buffer Cache, um ein vorzeitiges Herausaltern der Blöcke zu vermeiden.
2. einem Startup-Trigger, der die Daten schon während des Startups der Datenbank las.
Dadurch wurde der unvermeidliche Full Tablescan zu einer Zeit ausgeführt, in der die
Applikation ohnehin noch nicht zur Verfügung stand.
Das war innerhalb eines Tages implementiert und getestet und reduzierte die Zeit für die
Abfrage auf 12 Sekunden, was sehr akzeptabel war.
Das größte Problem war hier aber nicht die technische Lösung, sondern die Akzeptanz des
Projekts, hatte ich doch immerhin neue „ungetestete“ Features eingesetzt. Sicher ist es
richtig, dass Neuerungen in Oracle oft noch mit Kinderkrankheiten belastet sind, aber das
bedeutet ja nicht automatisch, dass man sie nicht einsetzen kann. Vielleicht sollte man sie
einfach ein bisschen besser testen als das, was man bereits kennt.
Oder um noch mal mit der Autoanalogie zu sprechen: Wenn Sie sich einen neuen Wagen
zulegen, ist es sehr ratsam, die Betriebsanleitung zu studieren. Könnte ja sein, das Sie dann
einiges machen können, was mit dem alten Wagen nicht möglich war. Wobei sich die Autotechnik – zumindest vordergründig für mich als „Endbenutzer“, ein Autohersteller wird
hier lebhaft widersprechen – zwischen zwei Versionen eines Wagens natürlich lange nicht
so stark ändert wie Software.
Nach wir vor habe ich den Anspruch, Ihnen einen möglichst kompakten Überblick zu bieten, was auch bedeutet, das manche Themen nach wie vor nur kurz angerissen werden. Eine Einführung in Oracle bietet dieses Buch nicht, sondern es soll als Überblick für den
Praktiker dienen. Ich setze bei allem voraus, dass Sie Oracle und vor allem SQL bereits
kennen und damit auch vertraut sind.
Das Buch ist in zehn Kapitel aufgeteilt. Im ersten Kapitel werden die unterschiedlichen
Tuning-Möglichkeiten, die in Oracle für das Design zur Verfügung stehen, vorgestellt. Das
ist gleichzeitig das umfangreichste Kapitel. Im nächsten Kapitel werden dann die Details
der Optimierung innerhalb von Oracle vorgestellt. Begriffe wie Optimizer oder Ausführungsplan werden in diesem Kapitel erläutert. Im dritten Kapitel werden die verschiedenen
Kennzahlen für das Tuning innerhalb der Datenbank vorgestellt. Das ist langweilig, aber
notwendig. Dafür ist das anschließende Kapitel sehr kurz, dort werden die verschiedenen
Vorgehensweisen für das Tuning knapp vorgestellt, und wir überlegen uns, wann welche
Methode eingesetzt werden sollte. Im nächsten Kapitel werden dann die verschiedenen
Tracingmethoden, die Sie für das Tuning benötigen, im Detail erläutert. Die restlichen Kapitel behandeln ausgewählte Aspekte des Tuning: In Kapitel 6 werden die Beziehungen
zwischen Performanz und physikalischer Speicherung untersucht. Kapitel 7 widmet sich
der Parallelisierung und allem, was damit zusammenhängt. Die Kapitel 8 bis 10 gehen
XII
Vorwort
dann noch auf ausgewählte Bereiche ein: Kapitel 8 behandelt die Optimierung über Outlines, Hints und den SQL Profiler. Diese Features sind vor allem Hilfsmittel für den Notfall, um bestehende Anweisungen zu beeinflussen. Kapitel 9 stellt das Tuning über Parameter dar. Diese Parameter können an verschiedenen Stellen gesetzt werden, entweder in
den Oracle-Parameterdateien – das ist dann die init.ora Datei oder das spfile – oder direkt
im laufenden Betrieb entweder für die ganze Datenbank oder auch nur für spezifische Sessions. Das abschließende Kapitel 10 untersucht die Zusammenhänge zwischen Performanz
und Hochverfügbarkeit und die Einstellungen für spezifische Betriebssysteme. Dieses letzte Kapitel ist sehr kurz, da es sich hier um sehr spezifische Einstellungen handelt. Abschließend noch ein kleines Glossar, das einige Oracle-Abkürzungen erläutert.
Alle Scripts für das Buch können Sie direkt beim Hanser Verlag herunterladen unter
http://downloads.hanser.de; ich habe mich bemüht, die Beispiele so einfach wie möglich
zu halten.
Ich hoffe, das Buch ist Ihnen nützlich.
Dättwil, im Sommer 2006
Frank Haas
XIII
Was this manual useful for you? yes no
Thank you for your participation!

* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project

Download PDF

advertisement