SQL-Tuning

Werbung
Tuning
Johannes Ahrends
Technical Director Presales Consulting
Quest Software GmbH
Copyright © 2006 Quest Software
Agenda
•
•
•
•
•
Was ist Tuning?
Beispiele aus der Praxis
Der Optimizer
Kleine Historie
Tuningmöglichkeiten
– Statistiken
– Zugriffsmethoden
– Hints
• Tuningwerkzeuge
• Datenbank-Parameter
• Vorausschauende Programmierung
1
Was ist Tuning?
Tuning ist die Summe aller
Ma
ßnahmen, welche die
Maßnahmen,
Optimierung der Antwortzeiten und
die Verbesserung der
Skalierbarkeit zum Ziele haben.
(Dr. Günter Unbescheid)
2
Tuningpotential
• Klassische Anforderung:
– 90% des Optimierungspotential liegt in den SQL-Befehlen
HW
Network
DB Changes
Indexes
90%
60%
SQL Statements
Quelle: Forrester Research
3
Übliche Beschwerden (1)
• Ein Anwender beschwert sich über die schlechten
Antwortzeiten der Applikation
• Grund?
–
–
–
–
Schlecht geschlafen
Schlechtes Wetter
Streit mit dem (Ehe)-Partner
Fehlerhafte Bedienung
• Lösung?
– Andere Anwender fragen (schwierig bei schlechtem Wetter)
– Nachsehen, ob in der Datenbank alles in Ordnung ist
– Tägliche oder stündliche Vergleichsmessungen
4
Übliche Beschwerden (2)
• Die Anwender beschweren sich über die schlechten
Antwortzeiten der Applikation
• Grund?
– Neue Anwendung
– Falsche Statistiken
– Anwendungen „kommen sich in die Quere“
• Lösung?
–
–
–
–
Anwendungen testen
Statistiken „einfrieren“
Anwendungen entkoppeln
Alarmierung bei zu langen Batchläufen
5
Übliche Beschwerden (3)
• Nach der Umstellung auf ein neues Release ist die
Anwendung wesentlich langsamer
• Grund?
– Anwender wollen die neue Anwendung nicht (torpedieren)
– Falsche Statistiken
– Falsche Parametrierung
• Lösung?
– Anwender schulen
– Neue Statistiken erstellen
– Datenbank / Instanzparameter überprüfen
6
Ein paar Praxisfälle (1)
• Problem:
– Nach Umstellung einer Datenbank von Version 8i auf Version 9i
beschweren sich die Anwender (1500!) darüber, dass die
Performance immer wieder einbricht (unkalkulierbar).
• Grund:
– In Version 9i wurden u.A. zwei neue Parameter eingeführt:
pga_aggregate_target und workarea_size_policy
– Default:
• pga_aggregate_target = 32 MB
• workarea_size_policy = AUTO Î sort_area_size ignoriert
• Lösung:
• pga_aggregate_target = 1000 MB
7
Ein paar Praxisfälle (2)
• Problem:
– Eine Anwendung scheint immer wieder zu hängen
• Grund:
– Aufgrund mangelndem Oracle Knowhow wurde die Datenbank
(Oraclei8i) mit Default-Einstellungen installiert
– Default für Redolog-Dateien (bis Oracle8i) Î 3 x 512 KB
• Lösung:
– Drei neue Redolog-Dateien mit je 50 MB
8
Ein paar Praxisfälle (3)
• Problem:
– Eine einfache Abfrage dauert ca. 5 Minuten
SELECT DISTINCT produktname,
warenwelt,
gruppe
FROM
produktinformationen
9
Grund: View auf View auf View auf …
10
Regelbasierter Optimizer (RBO)
• Grundsätzlich
– Untersucht so viele Pläne wie Tabellen in der Abfrage vorkommen
– Jeder Plan korrespondiert mit einer Tabelle am Anfang der Liste
– Nachfolgende Tabellen werden entsprechend der günstigsten
Zugriffsmethode angeordnet Î Join-Reihenfolge
– Bei jedem Join wählt der Optimizer zwischen Nested-Loop und
Sort-Merge
– Der (nach verschiedenen Kriterien) beste Plan wird behalten
– Bei gleicher Effizienz wird der Plan gewählt, der mit der letzten
Tabelle der FROM-Klausel beginnt
11
Kostenbasierter Optimizer (CBO)
• Grundsätzlich
– Analyse für n Permutationen der in der Abfrage vorkommenden
Tabellen durchgeführt
• n wird über den Initialisierungsparameter
optimizer_max_permutations gesetzt (Default 2000)
– Für jede Permutation werden verschiedene Pläne analysiert
(Zugriffs- und Join-Methoden unter Berücksichtigung aller hints),
und der mit den geringsten Kosten wird behalten
– Schließlich wird die kostengünstigste Permutation (und ihr Plan)
genutzt
• Die Kosten
– basieren auf der Anzahl logischer Reads, verfügbarem Speicher,
Prozessorauslastung
– werden aufgrund der Statistiken, die für die verschiedenen
Objekte verfügbar sind, kalkuliert
12
RBO oder CBO
• RBO
– Wird nicht von Oracle empfohlen
(kein Support mehr ab Oracle 10g)
– Neue Technologien (Bitmap, Hash Join, Partioning, …) werden
nicht angewendet
– Erlaubt keine Hints auf Statement-Ebene
• CBO
– von Oracle empfohlen
– Je besser die Statistiken, desto besser der Ausführungsplan!
13
Eine kleine Historie
•
•
•
•
•
•
Oracle 6:
Oracle 7:
Oracle 8:
Oracle8i:
Oracle9i:
Oracle 10g:
„Erste Tuningerfolge“
„Cost-Based-Optimizer“
„Statistiken fälschen“
„Function-Based Index“
„Systemstatistiken“
„Automatisches Tuning“
14
Oracle 6: Erste Tuningerfolge
• SQL:
– Rule-Based Optimizer -14 definierte Regeln
– Optimale Ergebnisse nur durch optimale Programmierung
• Wichtige Entwicklungen:
–
–
–
–
Extents
Tablespaces mit mehreren Datafiles
Row-level-locking
PL/SQL Programmierung (Procedural Option)
• Parameter:
– row_level_locking
– db_block_buffer
– log_buffer
• Datenbankgröße: < 1 GB
15
Oracle 7: Cost Based Optimizer
• SQL:
– Data-Warehouse Anwendungen bedingen den „intelligenten
Optimierer“
– Objektstatistiken als Bewertungsgrundlage
– Hohe Zeiten für Parsing (Permutationen)
• Wichtige Entwicklungen:
– Shared-Pool für die Wiederverwendung von Ausführungsplänen
– Bitmapped-Index
– Parallel Query
• Parameter:
– optimizer_mode
– shared_pool_size
• Datenbankgröße: 1 – 10 GB
16
Oracle 8: Statistiken fälschen
• SQL:
– Statistiken können angepasst und gespeichert werden
– Parallelisierung durch Partitionierung
• Wichtige Entwicklungen:
–
–
–
–
Partitionierung
Index Organized Tables
Reverse Key Indexing
dbms_stats Package
• Parameter:
– optimizer_max_permutation
– db_file_multiblock_read_count
• Datenbankgröße: 10 - 100 GB
17
Oracle8i: Function-Based Index
• SQL:
– Zwischenspeicherung von Ergebnissen in temporäre Tabellen
– Anwender können in Ressourcengruppen aufgeteilt werden
• Wichtige Entwicklungen:
–
–
–
–
–
–
Locally Managed Tablespaces
Online Index Reorganistion
Query Rewrite
Function Based Index
Plan Stability
Temporäre Tabellen
• Parameter:
– optimizer_index_cost_adj
– cursor_sharing
• Datenbankgröße: 10 - 100 GB
18
Oracle9i: Systemstatistiken
• SQL:
– Bessere Ressourcennutzung durch Systemstatistiken
– Reproduzierbare Ergebnisse durch Flashback Query
• Wichtige Entwicklungen:
–
–
–
–
–
–
Oracle Real Application Clusters
Automatic Segment Space Management
Multiple Blocksize
UNDO-Tablespaces
Native PL/SQL Compilation
Index Simulation
• Parameter:
– sga_max_size
– pga_aggregate_target
• Datenbankgröße: 100 – 2.000 GB
19
Oracle 10g: Automatisches Tuning
• SQL:
– Automatische Anpassung der Ressourcen für Buffer-Cache und
Shared Pool
– Automatisches Monitoring aller Objekte für optimale Statistiken
• Wichtige Entwicklungen:
–
–
–
–
–
–
Automatic Workload Repository (AWR)
Automatic Database Diagnostic Monitor (ADDM)
Automatic Storage Management (ASM)
Online Shrink
Automatic Memory Management
Active Session History Report (ASH)
• Parameter:
– sga_target
• Datenbankgröße: 100 – 20.000 GB
20
Was bietet das größte Tuningpotential?
•
V6
–
–
–
–
–
•
Umschreiben der Anwendung / Befehl
Indizierung
I/O Verteilung
Datenbank / Instanz Parametrierung
Reorganisation
V7
– Statistiken
– Hints
•
V9
– Real Application Clusters
– Systemstatistiken
– Unterschiedliche Blocksizes
•
V10
– feingranulare Statistiken
21
Erstellung von Statistiken
• Befehl ANALYZE
–
–
–
–
Mit Oracle7 eingeführt
Analysiert Tabellen und Indizes
Keine Systemstatistiken
Füllt Spalten chain_cnt, avg_space, avg_row_len
• Package dbms_utility
– analyze_schema
– analyze_database
– Führt den Befehl ANALYZE für mehrere Objekte aus
• Package dbms_stats
– Analysiert Objekt, Schema, Datenbank oder System
22
DBMS_STATS Package
• Erweiterte Analyse-Möglichkeiten für Partitionen,
Subpartitionen, geclusterte Tabellen, lokale und
globale Indizes
• Statistik-Gewinnung seriell oder parallel
• Nur Statistik-Werte für CBO werden ermittelt,
chained_rows, average_space, unused_blocks
werden nicht gepflegt
23
Automatische Statistiken
• Über DBMS_STATS-Package
DBMS_STATS.GATHER_SCHEMA_STATS('JAHR',
DBMS_STATS.GATHER_SCHEMA_STATS('JAHR',
options
options =>
=> 'GATHER
'GATHER AUTO');
AUTO');
DBMS_STATS.GATHER_DATABASE_STATS(
DBMS_STATS.GATHER_DATABASE_STATS(
options
options =>
=> 'GATHER
'GATHER AUTO');
AUTO');
• Erstellt neue Statistiken für Objekte, die sich um mehr
als 10% geändert haben
• Voraussetzung:
– Option MONITORING für Tabellen gesetzt
– dbms_stats.alter_schema_table_monitoring('SCOTT')
– dbms_stats.alter_database_table_monitoring(TRUE)
24
Gespeicherte Statistiken
• Statistiken können über DBMS_STATS gespeichert,
historisiert, ausgewertet und zurückgesetzt werden
• Prozeduren für Export, Import, Set der Statistiken
• Statistiken können somit „gefälscht“ werden, um das
Verhalten des CBO in einer Testdatenbank mit
Datenmengen aus der Produktion simulieren zu
können
25
Plan Stability
• Ausführungspläne werden als sog. Stored outlines
gespeichert
• Konservieren von Plänen, um stabile
Ausführungszeiten zu garantieren
• Stored Outlines können zwischen Systemen
transportiert werden
• Unterschiedliche „Kategorien“ von Stored Outlines
möglich
• User OUTLN mit 2 Tabellen OL$ und OL$HINTS
• Parameter
– QUERY_REWRITE_ENABLED = TRUE
26
Zugriffsmethoden
• Oracle ermöglicht den Zugriff auf Tabellendaten auf
drei Arten
– Lesen der gesamten Tabelle (Full Table Scan)
• Zugriff über Index
–
–
–
–
–
B*Tree Index
Bitmapped Index
Function-Based Index
Bitmapped Join Index
Index Organized Table (IOT)
• Zugriff über die direkte Angabe einer Row-ID
27
Full Table Scan
• Die gesamte Tabelle wird durch sogenannte multiblock-reads gescannt, deren Größe (in Blöcken) durch
den Parameter DB_FILE_MULTIBLOCK_READ_COUNT
festgelegt wird
• Alle Blöcke unterhalb der HWM = High Water Mark
werden gelesen
• Der Parameter beeinflusst den Cost Based Optimizer
28
B*Tree Index
SQL> SELECT * FROM PERSONEN WHERE PERSNR = 4711;
A
AA
PERSNR
PERSNR
BLOCK
BLOCK
11
–– 3000
3000
3001
3001 –– 8000
8000
……
AA
BB
Root-Block
B
PERSNR
PERSNR
BLOCK
BLOCK
PERSNR
PERSNR
BLOCK
BLOCK
11
100
100
……
AA
AA
AB
AB
3001
3001
4650
4650
……
BA
BA ……
BX
BX
––
––
100
100
230
230
––
––
3192
3192
4798
4798
Branch-Block
BX
PERSNR
PERSNR
ROWID
ROWID
PERSNR
PERSNR
ROWID
ROWID
11
22
……
b.aaa.10
b.aaa.10
b.ae1.03
b.ae1.03
4653
4653
……
4711
4711
b.aaa.03
b.aaa.03
Leaf-Block
b.abc.06
b.abc.06
PERSNR
PERSNR
VORNAME
VORNAME
NACHNAME
NACHNAME …
…
11
147
147
4711
4711
Hans
Hans
Klaus
Klaus
Trude
Trude
Meier
Meier
Schmidt
Schmidt
Herr
Herr
Table-Block
29
B*Tree Index
• Balanced Tree Index-Organisation
• Der Index wird, beginnend am Ursprung, blockweise
gescannt, dann erfolgt der Zugriff auf die
Tabellenblöcke
• Characteristika
– Speicherintensiv
– Speichert keine NULL-Werte
• Gute Performance bei
– Selektiven Auswahlbedingungen
– Zeilen mit gleichen Schlüsselwerten, die so weit wie möglich in
gleichen Tabellenblöcken gruppiert sind
30
B*Tree Index
• Effizient für Daten mit hoher Kardinalität.
– Beispiel: Ein Index auf einer date-Spalte
• Länge = 24 Byte Î 8Byte (Länge des Datentyps) + 10 Byte
(Länge der Rowid) + 6 Byte (Kontrollinformation)
• Bei einer Blockgröße (DB_BLOCK_SIZE) von 8 Kbyte ergibt
sich verfügbarer Raum von 8192 bytes pro Block –
Headergröße (zwischen 100 and 200 Bytes – im Beispiel 192
Bytes angenommen) = 8000 Bytes, zu 75% gefüllt = 6000
Bytes
• Ein Block kann also 6000 / 24 = 250 Schlüssel beinhalten.
• Ein Baum mit einer Tiefe von 3 kann demzufolge 250 x 250 x
250 = 15.625 Millionen Schlüssel verarbeiten.
• Um einen von 15 Millionen Werten zu ermitteln, genügen 3 I/OOperationen im Index plus eine I/O-Operation pro Zeile in der
Tabelle
31
B*Tree Index
• Ineffizient für:
– Einen Index auf der Primärschlüsselspalte einer kleinen Tabelle
(z.B. 10 Zeilen)
– Einen Index auf einer Spalte mit wenigen unterschiedlichen
Werten = niedrige Kardinalität (z.B. Geschlecht)
– Einen Index auf einer Spalte, in der oft Funktionen verwendet
werden (z.B. upper(lastname))
– Ein effizientes I/O-System mit Parallelisierungsmöglichkeiten
(z.B. db_file_multiblock_read_count hoch)
• In diesen Fällen sollte der Optimizer keine Indizes
verwenden
32
B*Tree Indexregeln
• Selektivität der Abfragen gewährleisten, die den
Indexschlüssel verwenden: weniger als 5 bis 15% der
Zeilen einer Tabelle als Ergebnis (Abhängig von der
Datenverteilung in der Tabelle)
• Spaltenreihenfolge bei Verwendung
zusammengesetzter Indizes beachten
• Keine Indizes bei kleinen Tabellen (außer uniqueIndizes)
• Für unique-Indizes PRIMARY KEY-oder UNIQUE
Constraints verwenden
• Abfragen für die Verwendung von Indizes optimieren
• DML-Performanceeinflüsse beachten
33
Bitmapped Index
• Jeder Schlüsselwert wird als Bitmap-Segment
gespeichert; der Zugriff auf Segmente erfolgt durch
einen B-Tree-Index
• Der Index wird wie ein B-Tree gescannt, anschließend
wird die Bitmap in ROWID's konvertiert
• Characteristika
– Weniger speicheraufwändig
– Speichert NULL-Werte
– Starker Einfluss auf DML-Operationen
• Effizient bei
– Kombinierten, nicht sehr selektiven Auswahlbedingungen
– Schnelle AND- und OR-Kombinationen über mehrere Indizes
34
Bitmapped Index
• Anwendungsregeln
– Mehr bei Abfragesystemen (OLAP, Datawarehouse) als bei
Transaktionssystemen (OLTP)
– Indexspalten mit geringer Kardinalität werden bei mehreren
Bedingungen durch AND und OR kombiniert
– Starker Performanceinfluss auf DML-Operationen
• Anlegen:
SQL> CREATE BITMAP INDEX name ON (column_list) ;
• Spezielle Parameter
– CREATE_BITMAP_AREA_SIZE:
– BITMAP_MERGE_AREA_SIZE:
Default-Wert = 8MB = OK
Default-Wert = 1MB = OK
35
Function Based Index
• Ein B-Tree Index, auf das Ergebnis einer Funktion
• Erlaubt die effiziente Verarbeitung von SQLStatements einschließlich der Verwendung von
Funktionen in der WHERE-Klausel
• Voraussetzungen
– QUERY_REWRITE_ENABLED = TRUE
(auf Instanz- oder Sitzungsebene)
– Statistiken für die Tabelle und den Index
– Costbased Optimizer
• Verhalten wie B*Tree Index
• Index kann bei Änderung der Funktion unusable
werden
36
Index Organized Table (IOT)
• Die gesamte Tabelle wird im B-Tree Index des
Primärschlüssels gespeichert
• Zugriff erfolgt wie beim B-Tree Index, jedoch ohne
Sekundärstruktur
• Characteristika
– Keine ROWID
– Zusätzliche Indizes sind möglich
– Geringerer Platzbedarf
– Overflow-area
• Effizient bei
– Zugriff mit Bereichs- oder Gleichheitsbegrenzenden Eigenschaften
des Primärschlüssels
37
Index Organized Table (IOT)
• Anwendungsregeln
– Eher für Tabellen geeignet, auf die allein über den Primärschlüssel
zugegriffen wird
– Eher für Tabellen geeignet, deren Zeilengröße geringer ist als die
halbe Blockgröße
38
Reverse Key Indexes
• Ein B-Tree-Index mit umgekehrter Anordnung der
Bytes in jeder Schlüsselspalte
• Index wird wie ein normaler B-Tree gescannt
• Characteristika
– Benachbarte Werte liegen im Index weit auseinander
• Effizient bei
– Index auf Primärschlüssel oder Datumsfelder, da hier in der Regel
immer ans Ende eingefügt wird
• Nachteile
– Keine Range-Scans möglich
• Anlegen
–
CREATE INDEX name ON (columns_list) REVERSE;
39
Bitmapped Join Index
• Speichert die Rowid's einer Tabelle (fact table) mit der
Spalteninformation einer anderen Tabelle (dimension
table)
• Wird hauptsächlich in Data Warehouses verwendet
CREATE
CREATE BITMAP
BITMAP INDEX
INDEX b_join_vertrieb
b_join_vertrieb ON
ON
DWH_KUNDEN(m.m_nachname)
DWH_KUNDEN(m.m_nachname)
FROM
FROM dwh_kunden
dwh_kunden k,
k, mitarbeiter
mitarbeiter mm
WHERE
WHERE k.vertrieb
k.vertrieb == m.m_nr
m.m_nr
COMPUTE
COMPUTE STATISTICS;
STATISTICS;
40
Handhabung von Indizes
• Beim Anlegen von Indizes zu beachten:
– Große SORT_AREA_SIZE
– Möglichkeiten der Parallelisierung nutzen
(Vorsicht! SORT_AREA_SIZE gilt für jeden Prozess)
– nologging-Option nutzen
– Speicherung in separatem Tablespace (IO-Verteilung)
• Administration:
– Tiefe eines Indexbaumes beobachten
SQL>
SQL> SELECT
SELECT index_name,
index_name, num_rows,
num_rows, blevel
blevel
FROM
FROM dba_indexes
dba_indexes
WHERE
WHERE blevel
blevel >> 2;
2;
41
Beispiel
SELECT
SELECT **
FROM
FROM auftraege
auftraege
WHERE
WHERE to_char(aufdatum,'DD.MM.YYYY')
to_char(aufdatum,'DD.MM.YYYY') == '05.10.2006'
'05.10.2006'
Indizierung?
CREATE
CREATE INDEX
INDEX idx_aufdatum
idx_aufdatum
ON
auftraege
ON
auftraege (to_char(aufdatum,'DD.MM.YYYY'));
(to_char(aufdatum,'DD.MM.YYYY'));
Bessere Lösung?
SELECT
SELECT **
FROM
FROM auftraege
auftraege
WHERE
WHERE aufdatum
aufdatum >=
>= to_date('05.10.2006',
to_date('05.10.2006', 'DD.MM.YYYY')
'DD.MM.YYYY')
AND
aufdatum
AND
aufdatum << to_date('05.10.2006',
to_date('05.10.2006', 'DD.MM.YYYY')
'DD.MM.YYYY') ++ 11
42
Zugriffsmethoden
• Full Table Scan
SELECT
SELECT vorname,
vorname, nachname
nachname
FROM
personen
FROM
personen
WHERE
ort
WHERE
ort == 'Köln';
'Köln';
Execution
Execution Plan
Plan
------------------------------------------------------------------------------------------------------00
SELECT
SELECT STATEMENT
STATEMENT Optimizer=CHOOSE
Optimizer=CHOOSE
11
00 TABLE
TABLE ACCESS
ACCESS (FULL)
(FULL) OF
OF 'PERSONEN'
'PERSONEN'
43
Zugriffsmethoden
• ROWID bekannt
SELECT
SELECT vorname,
vorname, nachname
nachname
FROM
personen
FROM
personen
WHERE
rowid
WHERE
rowid == 'AAALWYAAGAAAJiiAAA';
'AAALWYAAGAAAJiiAAA';
Execution
Execution Plan
Plan
------------------------------------------------------------------------------------------------------00
SELECT
SELECT STATEMENT
STATEMENT Optimizer=CHOOSE
Optimizer=CHOOSE
11
00 TABLE
TABLE ACCESS
ACCESS (BY
(BY USER
USER ROWID)
ROWID) OF
OF 'PERSONEN'
'PERSONEN'
44
Zugriffsmethoden
• Unique B-Tree-Index
SELECT
SELECT vorname,
vorname, nachname
nachname
FROM
personen
FROM
personen
WHERE
persnr
WHERE persnr == 4711;
4711;
Execution
Execution Plan
Plan
------------------------------------------------------------------------------------------------------00
SELECT
SELECT STATEMENT
STATEMENT Optimizer=CHOOSE
Optimizer=CHOOSE
11
00 TABLE
TABLE ACCESS
ACCESS (BY
(BY INDEX
INDEX ROWID)
ROWID) OF
OF 'PERSONEN'
'PERSONEN'
22
11
INDEX
INDEX (UNIQUE
(UNIQUE SCAN)
SCAN) OF
OF 'PK_PERSONEN'
'PK_PERSONEN'
(UNIQUE)
(UNIQUE)
Eindeutiger B-Tree-Index PK_PERSONEN
auf PERSONEN (persid)
45
Zugriffsmethoden
• Wertebereich oder Non-Unique B-Tree-Index
SELECT
SELECT vorname,
vorname, nachname
nachname
FROM
personen
FROM
personen
WHERE
nachname
WHERE
nachname == 'Ahrends';
'Ahrends';
Execution
Execution Plan
Plan
--------------------------------------------------------------------------------------------------------00
SELECT
SELECT STATEMENT
STATEMENT Optimizer=CHOOSE
Optimizer=CHOOSE
11
00 TABLE
TABLE ACCESS
ACCESS (BY
(BY INDEX
INDEX ROWID)
ROWID) OF
OF 'PERSONEN'
'PERSONEN'
22
11
INDEX
INDEX (RANGE
(RANGE SCAN)
SCAN) OF
OF 'IDX_NAME'
'IDX_NAME'
(NON-UNIQUE)
(NON-UNIQUE)
Einfacher B-Tree-Index IDX_NAME
auf PERSONEN (nachname)
46
Zugriffsmethoden
• B-Tree-Index ohne Zugriff auf die Tabelle
SELECT
SELECT vorname,
vorname, nachname
nachname
FROM
personen
FROM
personen
WHERE
WHERE nachname
nachname == 'Ahrends';
'Ahrends';
Execution
Execution Plan
Plan
--------------------------------------------------------------------------------------00
SELECT
SELECT STATEMENT
STATEMENT Optimizer=CHOOSE
Optimizer=CHOOSE
11
00 INDEX
INDEX (RANGE
(RANGE SCAN)
SCAN) OF
OF 'IDX_NAME'
'IDX_NAME'
B-Tree-Index IDX_NAME
auf PERSONEN (nachname, vorname)
47
Zugriffsmethoden
• Zugriff durch vollständigen B-Tree-Scan
SELECT
SELECT vorname,
vorname, nachname
nachname
FROM
personen
FROM
personen
WHERE
vorname
WHERE
vorname == 'Johannes';
'Johannes';
Execution
Execution Plan
Plan
------------------------------------------------------------------------------------------------------00
SELECT
SELECT STATEMENT
STATEMENT Optimizer=CHOOSE
Optimizer=CHOOSE
11
00 INDEX
INDEX (FAST
(FAST FULL
FULL SCAN)
SCAN) OF
OF 'IDX_NAME'
'IDX_NAME'
(NON-UNIQUE)
(NON-UNIQUE)
B-Tree-Index IDX_NAME
auf PERSONEN (nachname, vorname)
48
Zugriffsmethoden
• Zugriff durch Bitmap-Index auf einem einzelnen Wert
SELECT
SELECT vorname,
vorname, nachname
nachname
FROM
FROM personen
personen
WHERE
WHERE ort
ort == 'Köln';
'Köln';
Execution
Execution Plan
Plan
------------------------------------------------------------------------------------------------------------------00
SELECT
SELECT STATEMENT
STATEMENT Optimizer=CHOOSE
Optimizer=CHOOSE
11
00 TABLE
TABLE ACCESS
ACCESS (BY
(BY INDEX
INDEX ROWID)
ROWID) OF
OF 'PERSONEN'
'PERSONEN'
22
11
BITMAP
BITMAP CONVERSION
CONVERSION (TO
(TO ROWIDS)
ROWIDS)
33
22
BITMAP
BITMAP INDEX
INDEX (SINGLE
(SINGLE VALUE)
VALUE) OF
OF 'BIDX_ORT'
'BIDX_ORT'
Bitmap-Index BIDX_ORT auf PERSONEN (ort)
49
Zugriffsmethoden
• Zugriff durch Bitmap-Index auf mehreren Werten
SELECT
SELECT vorname,
vorname, nachname
nachname
FROM
personen
FROM
personen
WHERE
ort
WHERE ort == 'Köln'
'Köln' AND
AND nachname
nachname == 'Ahrends';
'Ahrends';
Execution
Execution Plan
Plan
----------------------------------------------------------------------------------------------------------------00
SELECT
SELECT STATEMENT
STATEMENT Optimizer=CHOOSE
Optimizer=CHOOSE
11
00 TABLE
TABLE ACCESS
ACCESS (BY
(BY INDEX
INDEX ROWID)
ROWID) OF
OF 'PERSONEN'
'PERSONEN'
22
11
BITMAP
BITMAP CONVERSION
CONVERSION (TO
(TO ROWIDS)
ROWIDS)
33
22
BITMAP
AND
BITMAP AND
44
33
BITMAP
BITMAP INDEX
INDEX (SINGLE
(SINGLE VALUE)
VALUE) OF
OF 'BI_ORT'
'BI_ORT'
55
33
BITMAP
INDEX
(SINGLE
VALUE)
OF
'BI_NAME'
BITMAP INDEX (SINGLE VALUE) OF 'BI_NAME'
Bitmap-Index BI_ORT auf PERSONEN (ort)
Bitmap-Index BI_NAME auf PERSONEN (nachname)
50
Hints
• Optimizer-Anweisungen für ein Statement
– Änderung des Optimizer-Modus' für die Dauer der Abfrage
(gilt für RBO und CBO)
– präzise Anweisungen an den Optimizer zur Ausführung eines
Statements (gilt nur für CBO)
• Für SELECT, UPDATE, DELETE oder Subqueries
• Syntax
– Kommentar gefolgt von einem Pluszeichen (+)
SELECT /*+ … */ deviceid FROM device;
– Können kombiniert werden
– Tabellen-Alias muss im Hint verwendet werden
• Ein fehlerhafter Hint wird ignoriert
51
Wichtige Hints - Zugriff
• /*+ FULL(table) */
– Zugriff über Full Table Scan
• /*+ INDEX(table [index, …]) */
– Zugriff über Index
• /*+ APPEND */
– Direct-Path Inserts möglich (Nologging-Option)
Standard bei paralleler Verarbeitung
52
Wichtige Hints - Join
• /*+ ORDERED */
– Join der Tabellen in der Reihenfolge der FROM-Klausel
• /*+ USE_NL(table1 [,table2,…]) */
– Nested-Loop-Join (verschachtelte Schleifen)
– Angegeben werden die Tabellen, die an eine bereits existierende
Ergebnissmenge angehängt werden sollen
• /*+ USE_MERGE(table1 [table2, …]) */
– Tabellen werden nach Join-Kriterium sortiert und dann verglichen
(Einstellung sort_area_size wichtig!)
• /*+ DRIVING_SITE(table) */
– Ausführung auf einer bestimmten Seite (in verteilten
Umgebungen)
53
Beispiel
54
Welches sind die wichtigsten Tools?
•
V6
–
–
–
–
–
–
•
Explain Plan
tkprof
bstat / estat
V$SQLAREA / V$SQLTEXT
SQL*Plus autotrace + timing
nst-Skripte
V7
– Oracle Enterprise Manager
•
V8
– Statspack
•
V9
– V$SQL / v$SQLPLAN
•
V10
–
–
–
–
ADDM
AWR
ASH
Anwendungstracing (dbms_monitor)
55
Explainplan
SQL>
SQL>
SELECT
SELECT aufnr
aufnr
FROM
positionen
FROM
positionen
WHERE
aufnr
WHERE aufnr not
not in
in (SELECT
(SELECT aufnr
aufnr FROM
FROM auftraegestorno);
auftraegestorno);
Execution
Execution Plan
Plan
------------------------------------------------------------------------------------------------------------------00
SELECT
SELECT STATEMENT
STATEMENT Optimizer=CHOOSE
Optimizer=CHOOSE
(Cost=740
(Cost=740 Card=49442
Card=49442 Bytes=395536)
Bytes=395536)
11
00 NESTED
LOOPS
(ANTI)
NESTED LOOPS (ANTI)
(Cost=740
(Cost=740 Card=49442
Card=49442 Bytes=395536)
Bytes=395536)
22
11
INDEX
INDEX (FAST
(FAST FULL
FULL SCAN)
SCAN) OF
OF 'PK_AUFTRAGSNR'
'PK_AUFTRAGSNR' (UNIQUE)
(UNIQUE)
(Cost=75
(Cost=75 Card=149639
Card=149639 Bytes=598556)
Bytes=598556)
33
11
INDEX
(UNIQUE
SCAN)
OF
'PK_AUFTRAEGE'
INDEX (UNIQUE SCAN) OF 'PK_AUFTRAEGE' (UNIQUE)
(UNIQUE)
(Cost=1
Card=100197
Bytes=400788)
(Cost=1 Card=100197 Bytes=400788)
• Die Anzeige kann je nach verwendetem Tool leicht
variieren, die Schlüsselwörter bleiben jedoch die
selben
56
Einen Ausführungsplan verstehen
• Beim kostenbasierten Optimizer sind zusätzliche
Informationen verfügbar
(nur AUTOTRACE oder EXPLAIN PLAN)
– COST: geschätzte Kosten (Information vom Optimizer)
– CARD (CARDINALITY): Anzahl der geschätzen Zeilen
– BYTES: Anzahl der geschätzen Bytes
57
Anwendungstracing
• Tracing von Anwendungen
– Erstellt eine Tracedatei im Verzeichnis user_dump_dest
ALTER
ALTER SESSION
SESSION SET
SET SQL_TRACE
SQL_TRACE == TRUE;
TRUE;
oder
oder
SID
SID und
und SERIAL#
SERIAL# aus
ausv$session
v$session ermitteln
ermittelnund
unddann:
dann:
execute
execute
dbms_system.set_sql_trace_in_session(SID,SERIAL#,TRUE);
dbms_system.set_sql_trace_in_session(SID,SERIAL#,TRUE);
• Tracedateien anschließend mit tkprof bearbeiten:
tkprof
tkprof <tracename>
<tracename> <outputdatei>
<outputdatei>
explain=<benutzer>/<kennwort>
explain=<benutzer>/<kennwort> [sys=no]
[sys=no]
[sort=<sortierung>]
[sort=<sortierung>]
58
SQL*Plus Autotrace
• Ausführung von Befehlen aus SQL*Plus
– Voraussetzung: PLAN-Table muss existieren
SQL> @?/rdbms/admin/utlxplan
– Nur möglich, wenn keine Bindevariablen verwendet werden
SET
SET AUTOTRACE
AUTOTRACE ON;
ON;
SET
SET AUTOTRACE
AUTOTRACE TRACEONLY;
TRACEONLY;
• Erstellung eines Ausführungsplans, ohne ein
Statement tatsächlich auszuführen
EXPLAIN
EXPLAIN PLAN
PLAN
[[ SET
SET STATEMENT_ID
STATEMENT_ID == 'name'
'name' ]]
[[ INTO
INTO <MYPLANTABLE>
<MYPLANTABLE> ]]
FOR
<statement>;
FOR
<statement>;
59
SQL-Tuning - V$SQL_PLAN
• Enthält für noch im Cache befindliche Cursor den
Ausführungsplan
• Spart EXPLAIN PLAN Kommando bzw.
entsprechendes Werkzeug
• Größere Sicherheit für den „richtigen“ Plan
60
SQL-Tuning - V$SQL_PLAN_STATISTICS
• Enthält für jedes Element des Ausführungsplans
(V$SQL_PLAN) zugehörige Statistiken (DISK_READS,
BUFFER_GETS, EXECUTIONS)
• Erstmals Kosten für Teilpläne!
• STATISTICS_LEVEL = ALL
SELECT
SELECT
FROM
FROM
a.*,
a.*, b.*
b.*
v$sql_plan
v$sql_plan a,
a,
v$sql_plan_statistics
v$sql_plan_statistics bb
WHERE
WHERE a.id
a.id == b.operation_id
b.operation_id
AND
a.address
AND
a.address == b.address
b.address
AND
a.address
AND
a.address == '78425FBC'
'78425FBC'
61
Statspack und AWR
• Schema perfstat mit einem Satz von StatistikTabellen
• Fügt mit jeder Ausführung der Prozedur
statspack.snap die momentanen Werte aus
unterschiedlichen V$-Tabellen in die Statistiktabellen
mit einer so genannten Snap-ID ein
• Auswertung von Zeiträumen zwischen zwei beliebigen
Snap-Ids
– Einschränkung: Die Instanz darf zwischenzeitlich nicht neu
gestartet worden sein!
• Schwellenwerte für Report können gesetzt werden
• AWR in Version 10g automatisch konfiguriert
62
Statspack Informationen
•
•
•
•
•
•
•
•
Load Profile
Ausnutzung der Instanz (Trefferraten, etc.)
Wait Events
SQL
Instance Activity
Tablespace IO
File IO
…
63
AWR (Beispiel)
64
Parameter für PGA-Größe (alt)
• bitmap_merge_area_size = 1048576
– Bestimmt die Größe bei Bitmap-Merge
• hash_area_size = 131072
– Bestimmt die Größe für Hash-Joins
Default: 2 * sort_area_size
• sort_area_size = 65536
– Bestimmt die Memory-Größe für allgemeine Sortierungen
• sort_area_retained_size = 65536
– Memorybedarf nach einer Sortierung
– Default: sort_area_size
Vorsicht:
Vorsicht:Jeder
JederProzess
Prozesskann
kanndiese
dieseRessourcen
Ressourcenbelegen!
belegen!
65
Parameter für PGA-Größe (Neu)
• workarea_size_policy = MANUAL
– Bestimmt, dass ein gestimmter Workspace zur Verfügung gestellt
wird
– Default abhängig von pga_aggreate_target, wenn dieser nicht
gesetzt, dann MANUAL, sonst AUTO
• pga_aggregate_target = 0
– Gibt die Gesamtgröße der zur Verfügung stehenden PGA an
– Alle Prozesse gemeinsam können diesen Speicherplatz
ausnutzen
– Je mehr konkurrierende Prozesse, umso kleiner die PGA des
Einzelnen
Vorsicht:
Vorsicht:
Andere
AnderePGA-Parameter
PGA-Parameterhaben
habenkeine
keineWirkung
Wirkungmehr!
mehr!
66
Parameter für Optimizer
• optimizer_mode = CHOOSE
– Legt den Standardoptimizer für die Datenbank fest
• optimizer_features_enable = 9.2.0
– Gibt an, welche Optimizerspezifischen Funktionen genutzt werden
können
• optimizer_index_cost_adj = 100
– Legt die prozentualen Kosten für einen Indexzugriff fest.
Ein Wert von 50 gibt an, dass ein Indexzugriff nur halb so teuer
wie normalerweise ist.
• optimizer_max_permutations = 2000
– Maximale Anzahl Permutationen, die für einen Join in Betracht
gezogen werden
– Wenn optimizer_features_enabled < 9.0 => 80000
67
Sonstige Parameter
• query_rewrite_enabled = FALSE
– Grundvoraussetzung für neue Funktionalitäten wie z.B. Query
Rewrite aber auch die Verwendung von Function-Based Indizes
• statistics_level = TYPICAL
– Gibt an, welche Statistiken für die Datenbank gesammelt werden
• timed_statistics = TRUE
– Es werden Statistiken mit Zeitangaben gesammelt
– Default abhängig von statistics_level:
• TRUE, wenn statistics_level = TYPICAL oder ALL,
sonst FALSE
• timed_os_statistics = 5
– Zeitintervall in Sekunden, nach denen Betriebssystemstatistiken
gesammelt werden
– Default abhängig von statistics_level:
• 5, wenn statistics_level = ALL, sonst 0
68
Parameter für Cursor-Sharing
• CURSOR_SHARING = EXACT
– Nur identische Statements werden "geshared"
• CURSOR_SHARING = FORCE
– Das System wandelt Literale in Bindevariablen um
– Bessere Ausnutzung des Sharedpools
– Vorsicht: kann in Oracle8i zu falschen Ergebnissen führen!
• CURSOR_SHARING = SIMILAR
– Wie FORCE, aber nur dann, wenn kein anderer Zugriffspfad
gewählt werden würde (z.B. durch Histogramme)
69
Dynamischer Shared und Large Pool
• Shared und Large Pools können dynamisch
vergrößert und verkleinert werden:
ALTER
ALTER
ALTER
ALTER
SYSTEM
SYSTEM
SYSTEM
SYSTEM
SET
SET
SET
SET
SHARED_POOL_SIZE
SHARED_POOL_SIZE == 64M;
64M;
LARGE_POOL_SIZE
LARGE_POOL_SIZE == 64M;
64M;
• Limitierungen:
– Die Größe ist ein Vielfaches der Granularität der Objekte
– Die gesamte SGA kann nicht größer werder als SGA_MAX_SIZE
70
Dynamischer Buffer Cache
• Der Buffer Cache kann dynamisch vergrößert oder
verkleinert werden
ALTER
ALTER SYSTEM
SYSTEM SET
SET DB_CACHE_SIZE
DB_CACHE_SIZE == 96M;
96M;
• Limitierungen:
– Vielfaches der entsprechenden db_block_size
– Die gesamte SGA kann nicht größer werder als SGA_MAX_SIZE
– DB_CACHE_SIZE kann nicht auf 0 gesetzt werden
71
Dynamische SGA Beispiel
Initialisierungsparameter
Initialisierungsparameter(init.ora):
(init.ora):
SGA_MAX_SIZE
== 128M
SGA_MAX_SIZE
128M
DB_CACHE_SIZE
== 96M
DB_CACHE_SIZE
96M
SHARED_POOL_SIZE
SHARED_POOL_SIZE == 32M
32M
SQL>
SQL>
=>
=>
ALTER
ALTER SYSTEM
SYSTEM SET
SET SHARED_POOL_SIZE
SHARED_POOL_SIZE == 64M;
64M;
insufficient
insufficientmemory
memory
SQL>
SQL>
SQL>
SQL>
=>
=>
=>
=>
ALTER
ALTER SYSTEM
SYSTEM SET
SET DB_CACHE_SIZE
DB_CACHE_SIZE == 64M;
64M;
ALTER
ALTER SYSTEM
SYSTEM SET
SET SHARED_POOL_SIZE
SHARED_POOL_SIZE == 64M;
64M;
insufficient
insufficientmemory
memoryerror
errormessage
message
check
checkV$BUFFER_POOL,
V$BUFFER_POOL,shrink
shrinkmuss
mussdurchgeführt
durchgeführtwerden
werden
SQL>
SQL>
=>
=>
ALTER
ALTER SYSTEM
SYSTEM SET
SET SHARED_POOL_SIZE
SHARED_POOL_SIZE == 64M;
64M;
Statement
Statementprocessed.
processed.
72
Empfehlungen für Caches
•
•
•
•
•
V$DB_CACHE_ADVICE
V$SHARED_POOL_ADVICE
V$PGA_TARGET_ADVICE
V$MTTR_TARGET_ADVICE
Beschreibung und Status in V$STATISTICS_LEVEL
73
Beispiel init.ora (1)
db_name
db_name
service_names
service_names
db_block_size
db_block_size
control_files
control_files
== JA102
JA102
== JA102
JA102
== 8192
8192
== ("/oradata1/JA102/control01.ctl",
("/oradata1/JA102/control01.ctl",
"/oradata2/JA102/control02.ctl",
"/oradata2/JA102/control02.ctl",
"/oradata1/JA102/control03.ctl")
"/oradata1/JA102/control03.ctl")
background_dump_dest
== /app/oracle/admin/JA102/bdump
background_dump_dest
/app/oracle/admin/JA102/bdump
user_dump_dest
== /app/oracle/admin/JA102/udump
user_dump_dest
/app/oracle/admin/JA102/udump
core_dump_dest
== /app/oracle/admin/JA102/cdump
core_dump_dest
/app/oracle/admin/JA102/cdump
log_archive_start
== true
log_archive_start
true
log_archive_dest
== /oradata3/JA102/archive/
log_archive_dest
/oradata3/JA102/archive/
log_archive_format
== arch_%s.arc
log_archive_format
arch_%s.arc
remote_login_passwordfile
remote_login_passwordfile == EXCLUSIVE
EXCLUSIVE
compatible
== 10.2.0.0.0
compatible
10.2.0.0.0
undo_management
=
AUTO
undo_management
= AUTO
undo_retention
== 10800
undo_retention
10800
undo_tablespace
== UNDOTBS1
undo_tablespace
UNDOTBS1
74
Beispiel init.ora (2)
db_cache_size
== 52428800
db_cache_size
52428800
db_file_multiblock_read_count
db_file_multiblock_read_count == 88
java_pool_size
== 00
java_pool_size
large_pool_size
== 8388608
large_pool_size
8388608
shared_pool_size
== 50331648
shared_pool_size
50331648
open_cursors
== 300
open_cursors
300
timed_statistics
== true
timed_statistics
true
job_queue_processes
== 22
job_queue_processes
query_rewrite_enabled
query_rewrite_enabled == true
true
processes
== 200
processes
200
fast_start_mttr_target
fast_start_mttr_target == 300
300
log_buffer
== 1048576
log_buffer
1048576
log_checkpoint_timeout
log_checkpoint_timeout == 00
pga_aggregate_target
== 104857600
pga_aggregate_target
104857600
aq_tm_processes
=
1
aq_tm_processes
= 1
75
Vorausschauende Programmierung
• Markieren von Anwendungsteilen mit
dbms_application_info
76
Anwendungstracing
• In der Anwendung:
dbms_application_info.set_module(
dbms_application_info.set_module(
module_name
module_name =>
=> 'Verkaufsbericht
'Verkaufsbericht (heute)'‚
(heute)'‚
action_name
action_name =>
=> 'Initialisierung')
'Initialisierung')
• Für einen speziellen Client:
dbms_session.set_identifier
dbms_session.set_identifier (client_id
(client_id =>
=> 'Lenz')
'Lenz')
• Tracing aktivieren:
dbms_monitor.serv_mod_act_trace_enable(
dbms_monitor.serv_mod_act_trace_enable(
service_name
service_name =>
=> 'SUN10G'‚
'SUN10G'‚
module_name
module_name =>
=> 'Verkaufsbericht
'Verkaufsbericht (heute)'‚
(heute)'‚
action_name
action_name =>
=> 'Initialisierung')
'Initialisierung')
dbms_monitor.client_id_trace_enable('Lenz');
dbms_monitor.client_id_trace_enable('Lenz');
77
Noch Fragen?
Johannes Ahrends
[email protected]
www.quest.com
Copyright © 2006 Quest Software
Herunterladen