Oracle 10G and Windows XP - Fachbereich Informatik und

Werbung
Universität Konstanz
Fachbereich
Informatik und Informationswissenschaft
SS 2007
Hausarbeit
Database Tuning & Administration
Seminar:
Dozent:
Assistant
Vorgelegt von:
Seminar: Database Tuning & Administration
Prof. Dr. Marc H. Scholl
Christian Gruen
Ketevan Karbelashvili & Irina Andrei
1
Inhaltsverzeichnis
1 Einführung............................................................................................................................... 3
1.1 Oracle Datenbank Enterprise Edition (EE) ...................................................................... 3
1.2 Oracle Datenbank Express Edition (XE) ......................................................................... 3
1.3 TPC-H .............................................................................................................................. 4
1.4 CYGWIN ......................................................................................................................... 4
1.5 Zeitmessung ..................................................................................................................... 5
2 DBMS Architektur .................................................................................................................. 5
2.1 Interne Ebene.................................................................................................................... 5
2.1.1 System Global Area (SGA)....................................................................................... 6
2.1.2 Program Global Area (PGA)..................................................................................... 8
2.1.3 Optimierung unter Oracle 10g EE............................................................................. 9
2.1.4 Optimierung unter Oracle 10g XE .......................................................................... 10
2.2 Konzeptuelle Ebene........................................................................................................ 12
2.2.1 Denormalisierung .................................................................................................... 13
2.2.2 Integration von Views in Anfragen......................................................................... 14
2.2.3 Partitionierung von Tabellen................................................................................... 17
2.2.4 Clustering ................................................................................................................ 22
2.2.5 Optimale Indexierung von Tabellen........................................................................ 35
3 Oracle Tuning Pack............................................................................................................... 46
3.1 Oracle Tuning Pack über PL/SQL ................................................................................. 47
3.2 Oracle Tuning Pack über Web Benutzeroberfläche ....................................................... 49
3.3 FAZIT............................................................................................................................. 51
4 FAZIT der Optimierung ........................................................................................................ 51
4.1 Oracle Tuning Tips......................................................................................................... 52
Literaturverzeichnis.................................................................................................................. 53
2
1 Einführung
„Tuning ist die Summe aller Maßnahmen, welche die Optimierung der Antwortzeiten und die
Verbesserung der Skalierbarkeit zum Ziele haben“.
(Dr. Günter Unbescheid)
Heutzutage spielen Datenbanken eine immer wichtigere Rolle in den verschiedensten Bereichen der
Industrie. Um diese Datenbanken und somit die Datenbestände sinnvoll auswerten zu können, werden
die verschiedensten Datenbank-Systeme und -Werkzeuge angeboten.
Um die Leistung der unterschiedlichen Systeme in Bezug auf bestimmte Eigenschaften wie
Anfragezeit und Performanz miteinander vergleichen zu können, müssen die zu vergleichenden DBSysteme standardisierten Tests unterzogen werden, was auch Benchmarking genannt wird. Das
Transaction Performance Processing Council (kurz. TPC) hat es sich zur Aufgabe gemacht
verschiedene Benchmarks zur Verfügung zu stellen, um die Leistungen der unterschiedlichen DBSysteme zu vergleichen. 1
Je nach Verwendungszweck werden die Benchmark-Datenbanken von TCP in 3 verschiedenen Typen
unterteilt:
• TPC-App - simuliert Daten die eines Web-Projektes im 24x7 Modus
• TPC-C - simuliert eine OLTP Datenbank, vorzugsweise im ERP-Bereich
• TPC-H - simuliert eine dispositive Datenbank im Bereich Data Warehouse. 2
Der Benchmark auf den sich diese Arbeit bezieht ist der TPC BenchmarkH (TPC-H).
Der TPC-H Benchmark wurde in dieser Arbeit unter Oracle 10g Express Edition (XE) und Oracle 10g
Enterprise Edition (EE) eingesetzt. Dabei als Betriebssystem wurde Windows XP benutzt.
1.1 Oracle Datenbank Enterprise Edition (EE)
Oracle 10g EE bietet effizientes, zuverlässiges und sicheres Datenmanagement
unternehmenskritischen Anwendungen wie beispielsweise umfangreiche On-Line Transaktions
Prozessing (OLTP) Umgebungen. Die Oracle Datenbank Enterprise Edition beinhaltet Werkzeuge und
Funktionen, um selbst höchste Ansprüche an Verfügbarkeit und Skalierbarkeit problemlos zu erfüllen.
Die Enterprise Edition unterstützt alle Rechnergrößen und hat keine Limitierung der CPU Kapazität.
1.2 Oracle Datenbank Express Edition (XE)
Oracle 10g XE ist die neueste Einstiegsvariante in die Oracle Welt. Die Oracle XE ist vollständig
kostenfrei und kann nach belieben entwickelt, eingesetzt und verteilt werden. Oracle XE mit der
weltweit führenden Datenbanktechnologie kann auf Rechnern aller Größen und ohne Beschränkung
der CPUs eingesetzt werden, ist jedoch beschränkt auf maximal 4 GB Nutzerdaten und die Nutzung
von maximal 1 GB Speicher sowie der Nutzung von lediglich 1 CPUs auf dem Hostserver. 3
1
2
3
[5] Realisierung des TPC-H-Schemas auf einem Oracle-Datenbanksystem
[6] TPC-H Schema erstellen
[7] Datenbank Lizenzen
3
1.3 TPC-H
Nach dem Download der Dateien TPCH unter http://www.tpc.org/tpch/ mussten ”Database Generator“
und ”Query Generator“ erstellt werden. Dafür musste erst das Makefile.suite angepasst werden:
• Makefile wurde erstellt.
• vier Parameter zur Anpassung an die vorhandene Datenbank wurden in Makefile eingestellt:
CC = gcc
DATABASE= SQLSERVER
MACHINE = LINUX
WORKLOAD = TPCH
Kompiliert wurde mit Hilfe des Programs CYGWIN
1.4 CYGWIN
nach dem beide Dateien QGEN.exe und DBGEN.exe erstellt wurden, mussten die Daten erstellt
werden und anschließend in das Datenbank importieren werden, dafür wurde auch mit SYGWIN
gearbeitet.
Cygwin ist eine Emulation der Linux-API. Mit Cygwin lassen sich Programme, die üblicherweise
unter POSIX-Systemen wie GNU/Linux, BSD und Unix laufen, auf Microsoft Windows portieren.
Folgende Befehle wurden unter SYGWIN ausgeführt, um 1 GB Zufallsdaten und 22 Zufallsqueries zu
erstellen:
• run dbgen -v -s 1 (generierte 1 GB an Zufallsdaten)
• run qgen -N -d 1 > 1_gen.sql (generierte 22 Zufallsqueries)
Als nächstes mussten die Erstellten Daten in die Datenbank importiert werden:
• Erst mussten die Tabellen erstellt wurden:
Type "sqlplus Benutzer/Password"
und
@ <full path>/dss.ddl
•
Als nächstes mussten die Tabellen mit den Daten gefüllt werden. Dafür musste für jede
Tabelle ein *.ctl File erstellt werden. Z.B. für CUSTOMER Tabelle:
load data
INFILE 'customer.tbl'
INTO TABLE CUSTOMER
FIELDS TERMINATED BY '|'
(C_CUSTKEY, C_NAME, C_ADDRESS, C_NATIONKEY, C_PHONE,
C_ACCTBAL, C_MKTSEGMENT, C_COMMENT)
•
Anschließend wurden die Daten mit dem Oracle SQL*Loader in die Datenbank eingespielt.
sqlldr Benutzer/Password control = customer.ctl
4
1.5 Zeitmessung
Für die Zeitmessung der Aufgaben wurden sie mehrmals ausgeführt, und die Ergebnisse in einer Excel
Datei gespeichert. Die Mittelwerten wurden weiter betrachten um Vergleiche zu machen und
Prozentsätze zu berechnen.
2 DBMS Architektur
Ein DBMS ist in drei Ebenen unterteilt:
• die interne Ebene (physische Sicht)
• die konzeptuelle Ebene (logische Sicht)
• die externe Ebene (benutzerspezifische Sicht) 4
2.1 Interne Ebene
Die interne Ebene kümmert sich um die physische Abspeicherung der Daten. Weiter ist die
Verwaltung des Pufferspeichers auf dieser Ebene angesiedelt.
4
[8] Datenbanksystem
5
Eine wichtige Aufgabe der internen Ebene ist die Sicherung der Datenkonsistenz zwischen
Datenspeicher und Memory (Synchronisation). Sollten sich Datenobjekte ändern, so verwaltet die
interne Ebene, wie die Speicherseiten verändert werden müssen. Ausserdem hat die interne Ebene die
Aufgabe, die Indizes zu verwalten. 5
2.1.1 System Global Area (SGA)
Zwei Faktoren bestimmen die Qualität eines Puffers. Zum einen die logischen Zugriffe (Logical
Read), unter denen man alle Zugriffe auf einen Block versteht, und zum anderen die physikalischen
Zugriffe, die alle Zugriffe auf einen Block auf der Festplatte ausdrücken (Physical Read).
Aus diesen Faktoren ergibt sich die Qualität des Puffers über folgende Formel:
Qualität (Hitratio) = Anzahl der Treffer/Anzahl der Abfragen × 100%
Die Datenbankpuffer der Oracle-Datenbank befinden sich in der System Global Area (SGA). SGA
fungiert als Hauptkommunikationsplattform für den schnellen Datenaustausch zwischen OracleProzessen. 6
Der globale Systembereich (SGA) von Oracle ist der Speicherbereich, der
beim Systemstart von Oracle zugeordnet wird und Speicherstrukturen zum
Speichern von Daten und Steuerungsinformationen enthält. 7
Die wichtigsten Puffer in der SGA der Oracle-Datenbank sind zur Übersicht in der folgenden Tabelle
dargestellt: 8
5
6
7
8
[8] Datenbanksystem
[9] Oracle-Datenbankadministration für SAP
[10] Oracle Konfigurationsoptionen
[9] Oracle-Datenbankadministration für SAP
6
Die für die folgenden Parameter definierten Werte wirken sich am stärksten auf die SGA-Größe aus:
•
•
•
LARGE_POOL_SIZE
SHARED_POOL_SIZE
DB_CACHE_SIZE
•
LOG_BUFFER
9
Man
kann
wegen
Performance
Engpässen
oder
bestimmten
Oracle
Fehlern
(z.B. ORA-04135) die Größe dieser Speicherbereiche dynamisch anpassen. Allerdings die Maximale
Grösse der SGA (SGA_MAX_SIZE) lässt sich nicht dynamisch ändern, sondern erfordert ein Reboot der
Datenbank. 10
2.1.1.1 Database Buffer Cache
„The buffer cache holds copies of data blocks so as they can be accessed
quicker by oracle than by reading them off disk.“11
Der Speicher wird über einen LRU-Algorithmus (Least Recently Used) verwaltet. Dadurch werden die
Blöcke, die am häufigsten gebraucht werden, immer im Speicher gehalten.
Der Database Buffer Cache besteht aus den Sub-Caches wie z.B:
• DB_KEEP_CACHE_SIZE ist die Größe des Keep Buffer Cache, welcher Blöcke zum
Wiederverwenden speichert.
• DB_BLOCK_SIZE bestimmt die Primary Block Size. 12
Default Cache Parameter Einstellungen unter ORACLE 10g EE nach Installierung.
Die Parameter aus vorhergehender Tabelle können dynamisch geändert werden, das heißt, ein Neustart
der Instanz ist nicht erforderlich.
9
10
11
12
[10] Oracle Konfigurationsoptionen
[11] Oracle-Server Bestandteile
[12] http://www.adp-gmbh.ch/ora/concepts/cache.html
[11] Oracle-Server Bestandteile
7
Shared Pool
Der Shared Pool speichert die zuletzt verwendeten SQL Statements und Datendefinitionen.
SHARED_POOL_SIZE definiert die Größe des Buffers für shared SQL und PL/SQL (Default 16MB bei
32bit bzw. 64MB bei 64 bit).
Java Pool
Der Java Pool ist optional und wird für Java verwendet. JAVA_POOL_SIZE definiert die Größe des
Java Pools (Default 24MB).
Large Pool
Der Large Pool ist ein optionaler Speicherbereich im SGA. Er wird für Session Memory verwendet bei
Shared Server. Weitere Anwendungen sind I/O, Backup/Restore (RMAN), ... Der Large Pool
verwendet kein LRU-Algorithmus. LARGE_POOL_SIZE definiert die Größe des Large Pools (Default 0).
LARGE_POOL_SIZE ist nicht dynamisch.
Streams Pool
Der Streams Pool ist neu in Oracle 10g und wird von Buffered Queues benutzt. Buffered Queues
wurden in Zusammenhang mit Oracle Streams eingeführt. Die Größe des Streams Pool wird mit dem
Parameter STREAMS_POOL_SIZE festgelegt. Der Streams Pool ist Bestandteil der SGA, er muss also in
den Wert für SGA_MAX_SIZE eingerechnet werden.
Redo Log Buffer
Der Redo Log Buffer ist ein Circular Buffer und speichert Änderungen von Datenblöcken. LOG_BUFFER
definiert die Größe des Redo Log Buffer in Bytes.
2.1.2 Program Global Area (PGA)
Der Listener-Prozess registriert Verbindungswünsche von User-Prozessen. Server Prozesse werden
dann auf Verlangen von User-Prozessen gestartet und führen stellvertretend dessen SQL-Statements
aus. Wenn ein Server-Prozess startet, wird ihm Arbeitsspeicher zugewiesen. Diesen nennt man
Program Global Area (PGA). Nach dem Beenden des User-Prozesses wird der PGA wieder
freigegeben.
Die PGA eines Prozesses enthält nur die Daten und Informationen, die von dieser benötigt oder
bearbeitet werden. Besonders bei speicherintensiven Sortier- und Hash-Operationen kommt der Größe
der PGA eine entscheidende Bedeutung zu.
Die Konfiguration der PGA hat sich allerdings seit dem Release Oracle 9i deutlich vereinfacht.
Ähnlich wie beim ASMM für die SGA passt Oracle die PGA-Bereiche aller Serverprozesse
automatisch an.
Der PGA besteht aus diesen Komponenten:
• Private SQL Area
• Persistent Area
8
•
•
•
Run-Time Area
Session Memory
SQL Work Areas 13
2.1.3 Optimierung unter Oracle 10g EE
Getestet wurde Datenbank 10g EE mit Primär-, Fremdschlüsseln mit Standart SGA, PGA
Einstellungen gegen Datenbank mit Primär-, Fremdschlüsseln und
• SGA=700
•
PGA=397
Gegen Standart eingestellten Werten nach der Installation
• SGA=432
•
PGA=143
Diese Abbildungen zeigen, dass den einzelnen Bestandteilen der SGA die Größen automatisch
zugewiesen werden, so braucht der Datenbankadministrator nicht ihnen die Werte manuell
zuzuweisen.
13
[11] Oracle-Server Bestandteile
9
Die Tests zeigten, dass obwohl die Laufzeit fast allen Queries nach der Optimierung mit SGA und
PGA sich verbessert hat, war diese Verbesserung nicht sehr gut und daher könnte man auch weiter mit
den alten Größen die durch das System vergeben wurden arbeiten.
2.1.4 Optimierung unter Oracle 10g XE
2.1.4.1 Buffer Cache Sub-Caches
Im unterschied zu Oracle 10g EE wurde es bei Oracle 10g XE auch versucht die Größen den einzelnen
Database Buffer Cache Sub-Caches manuell zu vergeben.
Default Cache Parameter Einstellungen unter ORACLE 10g XE nach Installierung
Getestet wurde
• Datenbank mit Primär-, Fremdschlüsseln und standard KEEP_CACHE_SIZE Einstellungen gegen
Datenbank mit Primär-, Fremdschlüsseln und KEEP_CACHE_SIZE =25M.
alter system set DB_KEEP_CACHE_SIZE = 25M;
Die folgende Abbildung zeigt, dass die Ergebnisse der
Ergebnisse der Standart DB_KEEP_CACHE_SIZE waren.
10
DB_KEEP_CACHE_SIZE = 25M
schlechter als die
2.1.4.1.1 FAZIT
Die Tests zeigten, dass bei dem manuellen Eingriff in die einzelnen Größen des Database Buffer
Cache man die Größen vorsichtig vergeben sollte und sich lieber auf die Standart eingestellten Größen
durch das System verlasen sollte.
2.1.4.2 Optimierung mit SGA und PGA unter Oracle 10g XE
Die Ergebnissen der Optimierung mit SGA und PGA unter Oracle 10g EE, waren den Ergebnissen der
Optimierung unter Oracle 10g XE ähnlich.
Default Einstellungen von SGA unter ORACLE 10g XE
Default Einstellung PGA von Oracle 10g XE
Getestet wurde Datenbank mit Primär-, Fremdschlüsseln mit Standart SGA, PGA Einstellungen gegen
Datenbank mit Primär-, Fremdschlüsseln und
• SGA = 512
•
PGA = 124
11
Die Graphische Darstellung zeigt, dass obwohl sich die Laufzeit der Query 5 nach der Optimierung
sehr verbessert hat, ist das Gesamtbild der Optimierung nicht sehr gut.
2.1.4.2.1 Fazit der Optimierung mit SGA und PGA
Stellt der Datenbankadministrator bei der Installation der gesamten Datenbank diese zwei Parameter
für die Speichergröße nicht ein so wird von der System die optimale Größe automatisch eingestellt, die
man auch beibehalten kann es sei man hat Schwierigkeiten mit Performance oder bekommt bestimmte
Oracle Fehler, dann können die Größen geändert werden.
Die Tests haben gezeigt, dass nachdem die SGA und PGA erhöht wurden, hat die Laufzeit der Queries
sich verbessert, aber weil es keine sehr gute Verbesserung war, könnte man auch weiter mit den alten
Größen arbeiten und versuchen die Queries mit den anderen Methoden zu Optimieren.
Schaut man aber sich das Gesamtbild der Optimierung unter oracle 10g EE an: Primär- und
Fremdschlüssel, PGA und SGA so sieht man, dass die Durchschnittlaufzeit der Queries im Vergleich
zum Anfangszustand sich merklich verbessert hat.
2.2 Konzeptuelle Ebene
Die konzeptuelle Ebene befasst sich mit der Abstraktion der Daten. D.h. die Darstellung der Daten, die
im physischen Schema vorliegen, werden so angepasst, wie sie der Benutzer haben möchte. 14
14
[8] Datenbanksystem
12
2.2.1 Denormalisierung
Die Denormalisierung ist die bewusste Rücknahme einer Normalisierung zum Zweck der
Verbesserung des Laufzeitverhaltens der Anfragen.
Die Denormalisierung reduziert die Tabellenzahl und verbessert die Antwortzeiten. Mindestens
theoretisch. Das ist der wichtigste Vorteil.
Die Nachteile sind: Datenredundanz und mehr Speicherplatz nötig, Aufwand um die redundanten
Daten konsistent zu halten, Gefahr von Datenanomalien. Die Synchronisierung der Updates
(Aktualisierungen) ist eine konstante Herausforderung für die Integrität der Daten in einer
denormalisierten Datenbank.
Für unsere Datenbank haben wir zuerst die Tabellen NATION und REGION unter Oracle 10g XE in
einer einzigen Tabelle transformiert:
CREATE TABLE nation_region
AS SELECT n_nationkey, n_name, n_comment, r_name AS n_r_name
FROM nation, region
WHERE n_regionkey=r_regionkey
Die Ergebnisse waren aber nicht überzeugend, wahrscheinlich weil die zwei Tabellen sehr klein sind.
Deswegen wurde auch die Tabelle supplier dazu addiert:
Die Denormalisierung der TPCH Datenbank
CREATE TABLE supp_nat_reg
AS SELECT s_suppkey, s_name, s_address, s_nationkey,
s_phone, s_acctbal, s_comment, n_name AS s_n_name,
n_r_name AS s_r_name
FROM supplier, nation_region
WHERE s_nationkey=n_nationkey
ALTER TABLE supp_nat_reg ADD CONSTRAINT pk_snr PRIMARY KEY (s_suppkey)
13
Nach dem Ausführung der geänderten Queries, waren die Ergebnisse überraschend. Die
Ausführungszeit bei Query 5 z.B. hat sich um 6% verschlechtert. Dasselbe ist auch bei Oracle EE
passiert:
Denormalisierung
04:19.2
03:36.0
Zeit
02:52.8
02:09.6
01:26.4
00:43.2
00:00.0
Q2
Q5
Q9
Q11
Q20
Querie s
Normal
Denormalisiert
Die Verschlechterung der Ausführungszeiten bei Oracle XE und EE
Insgesamt sind die Zeiten um 14%, beziehungsweise um 8,6% höher geworden. Um eine Erklärung zu
finden, wurde der Ausführungsplan von Q5 angeschaut.
Der Query Optimizer hat bei der Denormalisierten Datenbank keine Primärschlüssel benutzt und hat
die ganze neue Tabelle supp_nat_reg zugegriffen.
2.2.1.1 FAZIT
Es lohnt sich nicht die Datenbank zu denormalisieren. Obwohl das teoretisch bessere Zeiten bringen
sollte, bei Oracle gilt es nicht.
2.2.2 Integration von Views in Anfragen
Eine View (deutsch Sicht) ist eine logische Relation (auch virtuelle Relation oder virtuelle Tabelle) in
einem Datenbanksystem. Diese logische Relation wird über eine im Datenbankmanagementsystem
(DBMS) gespeicherte Abfrage definiert. Der Datenbankbenutzer kann eine View wie eine normale
Tabelle abfragen.
Neben den herkömmlichen Views gibt es noch so genannte Materialized Views (MS). Diese sind
Views, die physikalisch gespeichert werden, um Zugriffe zu beschleunigen.
14
Im Unterschied zu Klassischen Views werden Materialized Views nicht explizit in der SQL-Query
angesprochen. Eine materialisierte View ist eine Replik von Daten, die von einer Abfrage abgeholt
werden. Benutzerabfragen können zu einer materialisierten View umgeleitet werden, um Große
Tabellen während der Ausführung zu vermeiden. 15
Materialized Views ermöglichen die Ergebnismenge einer View als eigenständige Tabelle
abzuspeichern. Dies bringt besonders bei verteilten Datenbanken einen erheblichen
Performancegewinn, da Abfragen lokal durchgeführt werden können und hierdurch das Netzwerk bei
der Abfrage dieser Views nicht belastet wird.
Der Begriff Materialized View wurde mit der Version Oracle 8i eingeführt und ersetzt den bis dahin
verwendeten Begriff SNAPSHOT.
Der Aufruf der Refresh-Prozedur ermöglicht die manuelle Aktualisierung einer Materialized View
(MV).
•
EXEC DBMS_MVIEW.REFRESH (list=>‘Angestellte‘);
Syntax:
CREATE MATERIALIZED VIEW [schema.]mview
ON PREBUILT TABLE [{WITH | WITHOUT} REDUCED PRECISION]
[USING INDEX storage_options]
[{REFRESH [refresh_options] | NEVER REFRESH]
[FOR UPDATE] [{ENABLE|DISABLE} QUERY REWRITE]
AS subbquery; 16
Es wurde versucht die Laufzeit der Queries durch Materializes views zu beschleunigen, dafür wurden
die Queries: 7, 8, 9, 11, 20 und 22 benutzt.
Z.B.: Query 8:
Select o_year, sum (case when nation = 'BRAZIL' then volume else 0 end) / sum(volume) as mkt_share
from ( select extract(year from o_orderdate) as o_year, l_extendedprice * (1 - l_discount) as volume, n2.n_name
as nation
from part, supplier, lineitem, orders, customer, nation n1, nation n2, region
where p_partkey = l_partkey and
s_suppkey = l_suppkey and
l_orderkey = o_orderkey and
o_custkey = custkey and
c_nationkey = n1.n_nationkey and
n1.n_regionkey = r_regionkey and
r_name = 'AMERICA‘ and
s_nationkey = n2.n_nationkey and
o_orderdate between date '1995-01-01' and
date '1996-12-31‘ and
p_type = 'ECONOMY ANODIZED STEEL')
group by o_year
Order by o_year;
Create Materialized View
create materialized view mv_q8 as
select extract(year from o_orderdate) as o_year, l_extendedprice * (1 - l_discount) as volume, n2.n_name as nation
from part, supplier, lineitem, orders, customer, nation n1, nation n2, region
where p_partkey = l_partkey and
s_suppkey = l_suppkey and
l_orderkey = o_orderkey and
o_custkey = c_custkey and
c_nationkey = n1.n_nationkey and
n1.n_regionkey = r_regionkey and
r_name = 'AMERICA‘ and
s_nationkey = n2.n_nationkey and
o_orderdate between date '1995-01-01' and
15
16
[13] http://de.wikipedia.org/wiki/Sicht_%28Datenbank%29
[14] Materialized Views
15
date '1996-12-31' and
p_type = 'ECONOMY ANODIZED STEEL'
Umschreiben der Query 8
select o_year, sum(case when nation = 'BRAZIL' then volume else 0 end) / sum(volume) as mkt_share
from mv_q8
group by o_year
order by o_year;
Tests unter Oracle 10g EE
Tests unter Oracle 10g XE
2.2.2.1 FAZIT
Die durchgeführten Tests haben gezeigt, dass durch das Benutzen der Materialized Views die Laufzeit
der Queires sich erheblich verbessert hat, und sowohl unter Oracle 10g EE als auch unter Oracle 10g
XE ist fast die Gleiche Verbesserung zu sehen. Die Durchschnittslaufzeit der Queries lag nach der
Optimierung unter Oracle 10g EE bei 0,021 Sekunden (0,47 Sekunden vor der Optimierung) und unter
Oracle 10g XE bei 0,6 Sekunden (17 Sekunden vor der Optimierung).
Es ist sehr einfach und empfehlenswert mit Materialized Views zu arbeiten, falls man die Laufzeit der
Queries beschleunigen möchte.
16
2.2.3 Partitionierung von Tabellen
In den letzten Jahren wurden Datenbanken ebenso wie Tabellen immer größer. Heutzutage müssen
häufig Tabellen mit einem Platzbedarf von bis zu mehreren Terrabyte implementiert und verwaltet
werden. Die Verwaltung sehr großer Tabellen und Indizes kann sehr zeitaufwendig sein. Zudem ist oft
eine mangelnde Performance bei Datenzugriffen zu bemerken. Um dem entgegen zu wirken, führte
Oracle bereits in Version 8 die horizontale Partitionierung von Tabellen. Jede einzelne Partition kann
eigene physische Attribute (Tablespace, Storage-Parameter) haben und einzeln angesprochen werden.
Aus Sicht des Benutzers handelt es sich dabei weiterhin um eine einzige Tabelle.
Aufgrund eines „Partition Keys“ werden die eingefügten Daten automatisch in der jeweiligen Partition
gespeichert.
Einige Vorteile von Partitionierung sind:
• die einzelnen Partitionen können unabhängig voneinander verwaltet werden (z.B. Partitionen
löschen, reorganisieren und sichern)
• Performanceverbesserungen (befinden sich die in einer Abfrage benötigten Daten in einer
Partition, so muss nur auf diese Partition zugegriffen werden.)
• bei geeigneter Partitionierung können auf diese Art große Datenmengen schnell gelöscht
werden
Oracle stellt verschiedene Varianten der Partitionierung zur Verfügung.
Die RANGE-Partitionierung
Hierbei handelt es sich um eine Bereichspartitionierung. Ein typisches Beispiel ist die Partitionierung
einer Tabelle nach Datum, um alle Datensätze aus dem gleichen Quartal in einer eigenen Partition zu
speichern.
Die HASH-Partitionierung
Bei der Hash-Partitionierung haben die Datensätze innerhalb der Partitionen keine besondere
Bedeutung. Hier entscheidet das System mit Hilfe einer Hash-Funktion, in welche Partition ein
Datensatz abgelegt wird.
Beispiel: (Part Table wäre Möglich (Q16, 2))
CREATE TABLE part(P_PARTKEY
P_NAME
P_MFGR
P_BRAND
P_TYPE
P_SIZE
P_CONTAINER
P_RETAILPRICE
P_COMMENT
PARTITION BY HASH (p_size)
PARTITIONS 3
STORE IN (data1, data2, data3);
INTEGER NOT NULL,
VARCHAR(55) NOT NULL,
CHAR(25) NOT NULL,
CHAR(10) NOT NULL,
VARCHAR(25) NOT NULL,
INTEGER NOT NULL,
CHAR(10) NOT NULL,
DECIMAL(15,2) NOT NULL,
VARCHAR(23) NOT NULL)
In diesem Beispiel werden die einzelnen Datensätze vom System auf die drei verschiedenen
Partitionen verteilt. Dabei wird eine Hash-Funktion angewendet, die aufgrund der Werte in der Spalte
„p_size“ die Partition für die Speicherung bestimmt. Die Namen der Partitionen legt das System fest.
Diese Partitionierungsmethode kann angewendet werden, wenn in einer DSS Umgebung gearbeitet
wird (in der Regel wird die gesamte Tabelle eingelesen) und die Verteilung der Daten nicht bekannt
ist. Sie stellt eine einfache Möglichkeit zur Verfügung, Daten auf mehrere Tablespaces (Dateien) zu
verteilen, die dann mit Hilfe paralleler Zugriffsmechanismen bearbeitet werden können.
17
Im zweiten Teil des Artikels wird dann intensiv auf die Themen List- und Composite Partionierung
eingegangen. 17
Die LIST-Partitionierung
Die LIST-Partitionierung wurde in Oracle 9i speziell für Datenverteilungen eingeführt, die einzelnen
Werten folgen.
Beispiel:
CREATE TABLE region (R_REGIONKEY INTEGER NOT NULL,
R_NAME
CHAR(25) NOT NULL,
R_COMMENT VARCHAR(152))
TABLESPACE data1
PARTITION BY LIST (r_name)
(PARTITION region_Europe VALUES ('EUROPE') TABLESPACE data2,
PARTITION region_ASIA VALUES ('AISA') TABLESPACE data3,
PARTITION region_AMERICA VALUES ('AMERICA') TABLESPACE data4,
PARTITION region_default VALUES (DEFAULT) TABLESPACE data5
);
Die Datensätze werden aufgrund des Wertes in der Spalte "r_name " den Partitionen zugeordnet.
Datensätze mit dem "r_name " EUROPE werden zum Beispiel in die Partition "region_Europe"
eingefügt. Entspricht das spezifizierte "r_name " keinem der explizit aufgeführten Werte, so wird der
Datensatz der Partition "region_default" zugewiesen.
COMPOSITE-Partitionierung
Es gibt zudem die Möglichkeit die verschiedenen Partitionierungsmethoden miteinander zu
kombinieren, um so eine Partitionierung auf zwei Ebenen zu erreichen. Dadurch ist es möglich, eine
Partition wiederum in eine bestimmte Anzahl an Subpartitionen aufzuteilen. Das kann sinnvoll sein,
wenn die einzelnen Partitionen einer Tabelle noch sehr groß sind. Man unterscheidet die RANGELIST- und die RANGE-HASH-Partitionierung.
Beispiel für eine RANGE-LIST-Partitionierung:
CREATE TABLE lineitem
( L_ORDERKEY
INTEGER NOT NULL,
L_PARTKEY
INTEGER NOT NULL,
L_SUPPKEY
INTEGER NOT NULL,
L_LINENUMBER
INTEGER NOT NULL,
L_QUANTITY
DECIMAL(15,2) NOT NULL,
L_EXTENDEDPRICE
DECIMAL(15,2) NOT NULL,
L_DISCOUNT
DECIMAL(15,2) NOT NULL,
L_TAX
DECIMAL(15,2) NOT NULL,
L_RETURNFLAG
CHAR(1) NOT NULL,
L_LINESTATUS
CHAR(1) NOT NULL,
L_SHIPDATE
DATE NOT NULL,
L_COMMITDATE
DATE NOT NULL,
L_RECEIPTDATE
DATE NOT NULL,
L_SHIPINSTRUCT
CHAR(25) NOT NULL,
L_SHIPMODE
CHAR(10) NOT NULL,
L_COMMENT
VARCHAR(44) NOT NULL)
PARTITION BY RANGE (L_RECEIPTDATE)
SUBPARTITION BY LIST (L_SHIPMODE)
SUBPARTITION TEMPLATE
(SUBPARTITION mailship VALUES ('MAIL', 'SHIP') TABLESPACE data2,
SUBPARTITION andere VALUES (DEFAULT) TABLESPACE data3)
(PARTITION Jahr_1994 VALUES LESS THAN (TO_DATE('1995-01-01','YYYY/MM/DD')),
PARTITION Andere_Jahre VALUES LESS THAN (TO_DATE('1994-01-01','YYYY/MM/DD')));
17
[15] Oracle: Einsatz von Partitioning
18
Die Tabelle wird mit vier Partitionen erstellt, die wiederum in jeweils zwei Subpartitionen
aufgesplittet sind. Jede Partition nimmt die Subpartitions-Beschreibungen aus dem angegebenen
SUBPARTITION TEMPLATE. Die generierten Subpartitionsnamen sind jeweils Jahr_1995 und
Andere_Jahre,... Datensätze aus dem Juni 1994 werden der Partition Jahr_1994 zugeordnet. In
Abhängigkeit des Wertes in der Spalte "L_SHIPMODE " werden sie dann einer der beiden
Subpartitionen zugeordnet. Lautet das "L_SHIPMODE " MAIL, so wird der Datensatz in die
Subpartition mailship eingefügt.
Indizes
Bei der Zugriffsoptimierung spielen Indizes eine bedeutende Rolle. Dies gilt sowohl bei nichtpartitionierten Tabellen als auch bei partitionierten Tabellen. Beim Anlegen eines Indexes auf eine
partitionierte Tabelle hat man verschiedene Möglichkeiten: Zum einen kann ein Index über die
gesamte Tabelle erstellt werden und zum anderen kann ein partitionierter Index erstellt werden. Dabei
kann der Index entweder gleichpartitioniert sein oder der Index kann mit einer eigenen
Partitionierungsstrategie erstellt werden. Ist ein Index gleichpartitioniert, so spricht man von einem
lokalen Index, anderenfalls von einem globalen Index. Die lokalen Indizes sind im Zusammenhang
mit der Verbesserung von Performance und Fehlertoleranz von großer Bedeutung.
Beispiel für die Erstellung eines lokalen Indizes:
create tablespace idx1 datafile 'E:\oracle\product\10.2.0\oradata\orcl\idx1.dbf' size 1M autoextend on next 500k;
create tablespace idx2 datafile 'E:\oracle\product\10.2.0\oradata\orcl\idx2.dbf' size 1M autoextend on next 500k;
create tablespace idx3 datafile 'E:\oracle\product\10.2.0\oradata\orcl\idx3.dbf' size 1M autoextend on next 500k;
create tablespace idx4 datafile 'E:\oracle\product\10.2.0\oradata\orcl\idx4.dbf' size 1M autoextend on next 500k;
create tablespace idx5 datafile 'E:\oracle\product\10.2.0\oradata\orcl\idx5.dbf' size 1M autoextend on next 500k;
CREATE INDEX l_lineitem_idx
ON lineitem (L_SHIPDATE, L_ORDERKEY, L_LINENUMBER) LOCAL
(PARTITION p1 TABLESPACE idx1,
PARTITION p2 TABLESPACE idx2,
PARTITION p3 TABLESPACE idx3,
PARTITION p4 TABLESPACE idx4,
PARTITION p5 TABLESPACE idx5
);
Der Index, der auf die Spalte "l_orderkey, L_LINENUMBER" gelegt wird, besitzt die gleichen
Partitionen wie die Tabelle "lineitem" (s.o.). Das bedeutet, dass Einträge aus einer Indexpartition auf
genau eine Tabellenpartition verweisen. Diese Art von Index ist für Anfragen, die einzelne Partitionen
betreffen sinnvoll.
Beispiel für einen nicht-partitionierten, globalen Index
CREATE INDEX l_orderkey_idx
ON lineitem (l_orderkey);
Der so erstellte Index ist nicht partitioniert. Diese Art von Indizes ist für Anfragen, die die gesamte
Tabelle betreffen (und nicht einzelne Partitionen) sinnvoll.
Beispiel für einen partitionierten, globalen Index:
CREATE INDEX l_orderkey_idx
ON lineitem (l_shipdate, l_orderkey)
GLOBAL PARTITION BY RANGE (l_shipdate)
(PARTITION p1
VALUES LESS THAN (TO_DATE('1993-12-31','YYYY/MM/DD'))
19
TABLESPACE p1,
PARTITION p2
VALUES LESS THAN (TO_DATE('1995-03-14','YYYY/MM/DD'))
TABLESPACE p2,
PARTITION p3
VALUES LESS THAN (TO_DATE('1995-10-02','YYYY/MM/DD'))
TABLESPACE p3,
PARTITION p4
VALUES LESS THAN (TO_DATE('1997-01-01','YYYY/MM/DD'))
TABLESPACE p4,
PARTITION p5
VALUES LESS THAN (MAXVALUE)
TABLESPACE p5
);
Voraussetzung für die Partitionierung ist, dass das Partitionierungskriterium ein Prefix ist (die zuerst
indizierte Spalte oder Spaltenkombination). 18
2.2.3.1 Tests unter Tabellen Partitionierung
Getestet wurde die RANGE-Partitionierung mit der Tabelle Lineitem, und die LIST-Partitionierung
mit der Tabelle Part.
Die RANGE-Partitionierung wurde mit und ohne den partitionierten lokalen Index getestet. Ein
partitionierter Index geht Hand in Hand mit partitionierten Tabellen. Tatsächlich wird eine
partitionierte Tabelle normalerweise standardmäßig über partitionierte Index verfügen. Ein PräfixIndex ist als Index definiert, dessen am weitesten links stehende Spalten exakt mit denen des
Partitionsschlüssels übereinstimmen. Im Zusammenhang mit partitionierten Indices ist das Konzept
von Präfix-Indices aus folgenden Gründen wichtig:
Eindeutige Präfix-Indices stellen sicher, dass man nur noch auf eine Indexpartition zugreifen muss, um
an die Daten zu gelangen.
Nicht eindeutige Präfix-Indices stellen immer noch sicher, dass man nur eine Indexpartition benötigt,
wenn man den vollständigen Partitionsschlüssel als Bestandteil der WHERE-Klausel angibt. Die
Ausnahme hierzu ist, dass alle Partitionen durchsucht werden, wenn man nur einen Teil des
Partitionsschlüssels angibt.
Die Partitionierung wurde bei den Tabellen Region und Nation nicht benutzt, weil sie viel zu klein
sind.
Die RANGE-Partitionierung auf der Tabelle „Lineitem“ hat bei fast allen Queires deutliche
Verbesserungen gebracht.
create tablespace p1 datafile 'E:\oracle\product\10.2.0\oradata\orcl\p1.dbf' size 1M autoextend on next 500k
create tablespace p2 datafile 'E:\oracle\product\10.2.0\oradata\orcl\p2.dbf' size 1M autoextend on next 500k
create tablespace p3 datafile 'E:\oracle\product\10.2.0\oradata\orcl\p3.dbf' size 1M autoextend on next 500k
create tablespace p4 datafile 'E:\oracle\product\10.2.0\oradata\orcl\p4.dbf' size 1M autoextend on next 500k
create tablespace p5 datafile 'E:\oracle\product\10.2.0\oradata\orcl\p5.dbf' size 1M autoextend on next 500k
CREATE TABLE LINEITEM ( L_ORDERKEY
L_PARTKEY
L_SUPPKEY
L_LINENUMBER
L_QUANTITY
L_EXTENDEDPRICE
18
INTEGER NOT NULL,
INTEGER NOT NULL,
INTEGER NOT NULL,
INTEGER NOT NULL,
DECIMAL(15,2) NOT NULL,
DECIMAL(15,2) NOT NULL,
[16] Oracle: Einsatz von Partitioning (Teil 2)
20
L_DISCOUNT
DECIMAL(15,2) NOT NULL,
L_TAX
DECIMAL(15,2) NOT NULL,
L_RETURNFLAG
CHAR(1) NOT NULL,
L_LINESTATUS
CHAR(1) NOT NULL,
L_SHIPDATE
DATE NOT NULL,
L_COMMITDATE
DATE NOT NULL,
L_RECEIPTDATE
DATE NOT NULL,
L_SHIPINSTRUCT
CHAR(25) NOT NULL,
L_SHIPMODE
CHAR(10) NOT NULL,
L_COMMENT
VARCHAR(44) NOT NULL)
PARTITION BY RANGE (L_SHIPDATE)
(PARTITION p1
VALUES LESS THAN (TO_DATE('1993-12-31','YYYY/MM/DD'))
TABLESPACE p1,
PARTITION p2
VALUES LESS THAN (TO_DATE('1995-03-14','YYYY/MM/DD'))
TABLESPACE p2,
PARTITION p3
VALUES LESS THAN (TO_DATE('1995-10-02','YYYY/MM/DD'))
TABLESPACE p3,
PARTITION p4
VALUES LESS THAN (TO_DATE('1997-01-01','YYYY/MM/DD'))
TABLESPACE p4,
PARTITION p5
VALUES LESS THAN (MAXVALUE)
TABLESPACE p5
);
In diesem Beispiel wird die Tabelle “ LINEITEM” erstellt, die in fünf Partitionen aufgeteilt ist. In der
ersten Partition werden alle Bestellungen gespeichert, deren Bestelldatum vor dem '1993-12-31' liegt.
In der zweiten Partition werden die Datensätze gespeichert, deren Bestelldatum vor dem '1995-03-14'
liegt und die nicht in der ersten Partition gespeichert sind. Die letzte Partition nimmt alle Datensätze
auf, die keiner der anderen Partitionen zugeordnet werden können, da durch die Verwendung des
Schlüsselwortes MAXVALUE keine Obergrenze definiert ist. Die einzelnen Partitionen werden hier
in unterschiedliche Tablespaces abgelegt. Diese Partitionierungsmethode ist gut geeignet für die
Ablage historischer Daten, da das Löschen alter Daten sowie das Hinzufügen neuer Partitionen einfach
und schnell durchführbar ist.
Insbesondere die Query 10, die sonst ungefähr 6 Minuten gebraucht hat, lief mit partitionierten lokalen
Index nur noch 1,4 Minuten. Die Graphische Darstellungen zeigten, dass die besten Ergebnisse kamen
mit unter partitionierten lokalen Index heraus, die zweit Besten Ergebnisse waren unter der Benutzung
des Primärschlüssels zu sehen.
Nachdem
der
partitionierte
lokale
Index
auf
(L_SHIPDATE,
L_ORDERKEY,
L_LINENUMBER)erstellt wurde, haben die Queries im Durchschnitt nur noch 0,45 Sekunden
gebraucht und ohne den partitionierten lokalen Index aber mit dem Primärschlüssel auf
(L_ORDERKEY, L_LINENUMBER) liefen die Queries im Durchschnitt 0,48 Sekunden.
21
LIST-Partitionierung wurde auf Tabelle Part erstellt und hat auch gute Ergebnisse gezeigt. Z.B. die
Laufzeit der Query 19 hatte sich von 0,42 auf 0,32 verbessert.
create tablespace data1 datafile 'E:\oracle\product\10.2.0\oradata\orcl\data1.dbf' size 1M autoextend on next 500k;
create tablespace data2 datafile 'E:\oracle\product\10.2.0\oradata\orcl\data2.dbf' size 1M autoextend on next 500k;
create tablespace data3 datafile 'E:\oracle\product\10.2.0\oradata\orcl\data3.dbf' size 1M autoextend on next 500k;
create tablespace data4 datafile 'E:\oracle\product\10.2.0\oradata\orcl\data4.dbf' size 1M autoextend on next 500k;
create tablespace data5 datafile 'E:\oracle\product\10.2.0\oradata\orcl\data5.dbf' size 1M autoextend on next 500k;
CREATE TABLE part
(P_PARTKEY
P_NAME
P_MFGR
P_BRAND
P_TYPE
P_SIZE
P_CONTAINER
P_RETAILPRICE
P_COMMENT
INTEGER NOT NULL,
VARCHAR(55) NOT NULL,
CHAR(25) NOT NULL,
CHAR(10) NOT NULL,
VARCHAR(25) NOT NULL,
INTEGER NOT NULL,
CHAR(10) NOT NULL,
DECIMAL(15,2) NOT NULL,
VARCHAR(23) NOT NULL)
TABLESPACE data1
PARTITION BY LIST (p_container)
(PARTITION SM VALUES ('SM CASE', 'SM BOX', 'SM PACK', 'SM PKG') TABLESPACE data2,
PARTITION MED VALUES ('MED BAG', 'MED BOX', 'MED PKG', 'MED PACK') TABLESPACE data3,
PARTITION LG VALUES ('LG CASE', 'LG BOX', 'LG PACK', 'LG PKG') TABLESPACE data4,
PARTITION region_default VALUES (DEFAULT) TABLESPACE data5);
create tablespace idx11 datafile 'E:\oracle\product\10.2.0\oradata\orcl\idx11.dbf' size 1M autoextend on next 500k;
create tablespace idx44 datafile 'E:\oracle\product\10.2.0\oradata\orcl\idx44.dbf' size 1M autoextend on next 500k;
create tablespace idx22 datafile 'E:\oracle\product\10.2.0\oradata\orcl\idx22.dbf' size 1M autoextend on next 500k;
create tablespace idx33 datafile 'E:\oracle\product\10.2.0\oradata\orcl\idx33.dbf' size 1M autoextend on next 500k;
CREATE INDEX p_part_idx
ON part (p_container, p_size, p_brand, p_partkey) LOCAL
(PARTITION SM TABLESPACE idx11,
PARTITION MED TABLESPACE idx22,
PARTITION LG TABLESPACE idx33,
PARTITION region TABLESPACE idx44
);
2.2.3.1.1 FAZIT
Die Tests haben gezeigt, dass Tabellen Partitionierung eine sehr gute Methode ist, um die Laufzeit der
Queries zu beschleunigen, dabei wichtig ist, dass die Tabellen die Partitioniert nicht sehr klein sind,
damit die Laufzeit der Queries auch merklich verbessert werden kann.
Leider ist unter Oracle 10g XE die Funktion für Partitionieren nicht aktiviert (ORA-00439: Funktion
nicht aktiviert: Partitioning), daher Partitionierung konnte nur unter Oracle 10g EE getestet werden.
2.2.4 Clustering
Clustering ist ein Mittel zur Strukturierung der Daten in ein oder mehreren Tabellen, so dass deren
Zeilen physisch nebeneinander liegen. 19
Ein Cluster kann eingesetzt werden, wenn mehrere Tabellen eine Zeile desselben Datentyps und
derselben Größe am selben Speicherort aufnehmen. Dadurch lässt sich der Speicherbedarf reduzieren
und in einigen Fällen der Datenzugriff beschleunigen. Der wesentliche Nachteil in Form von
19
[17] Oracle SQL im Überblick
22
Performanzeinbußen tritt bei Aktionen zu Tage, an denen Aktualisierungs-, Einfüge- und
Löschoperationen beteiligt sind. Der DBA sollte den zu erwartenden Mix von Transaktionsarten für
die zu clusternden Tabellen ermitteln und nur diejenigen von ihnen clustern, die häufig miteinander
verknüpft werden und nicht viele Aktualisierungs-, Einfüge- und Löschoperationen erfahren.
Cluster speichern gemeinsam genutzte Datenwerte in denselben physischen Blöcken (die
Schlüsselwerte des Clusters). Bei häufig miteinander verknüpften Tabellen kann dies den Zugriff
beschleunigen; bei Tabellen auf die häufig getrennt voneinander zugegriffen wird, ist das Verknüpfen
keine Antwort. Ein einzelner Tabellencluster zwingt die Schlüsselwerte für diese Tabelle in eine
einzige Gruppe von Blöcken, wodurch der Zugriff auf diese Tabelle beschleunigt wird. Üblicherweise
kommt bei dieser Art von Einzeltabellenclustern auch eine Hash – Struktur zum Einsatz, die die
Zugriffszeiten noch verbessert. 20
Man unterscheidet:
•
Index Cluster: Der Cluster Key entspricht einem oder mehreren Tabellenattributten.
•
Hash Cluster: Der Cluster Key das Ergebnis der Anwendung einer Hashfunktion auf ein oder
mehrere Tabelenattribute.
Idealfall: Der Cluster Key verteilt die Datensätze so, dass pro Cluster Key ein Block benötigt wird.
Erzeugen von Cluster
Ein Cluster wird durch folgenden Befehl erzeugt:
CREATE CLUSTER clustername (attr1 datentyp1 [,attr2 datentyp2] ... )
[PCTUSED integer] [PCTFREE integer]
[SIZE integer [K|M] ]
[INDEX | [HASH IS attr] HASHKEYS integer]
Die Attribute attr1, attr2,... geben den Clusterschlüssel an. Die Parameter PCTUSED und PCTFREE
steuern den Füllgrad von Datenblöcken. Der Parameter PCTUSED bezeichnet dabei den Anteil
(Angabe in Prozent) eines Datenblocks, der mindestens belegt sein sollte. PCTFREE gibt an, wie viel
Prozent des Datenblocks mindestens frei sein sollten. Die Summe aus PCTUSED und PCTFREE darf
den Wert 100 nie überschreiten. Der Parameter SIZE bestimmt, wie viele Bytes innerhalb eines
Datenblockes für denselben Clusterschlüssel-Wert bzw. Hash-Wert verwendet werden. Der Wert darf
die Größe eines Datenblockes nicht überschreiten. Wird die Angabe von SIZE weggelassen, so
reserviert Oracle einen Datenblock pro Schlüsselwert. Die Angabe von INDEX erzeugt einen IndexCluster, während durch HASHKEYS n ein Hash-Cluster mit n verschiedenen Hash-Werten (Buckets)
erzeugt wird. Der Wert n wird zuvor intern auf die nächst größere Primzahl aufgerundet.
Erzeugen von Indizes
Indizes werden durch folgende Anweisung erzeugt:
CREATE INDEX indexname ON { tabellenname(attr1 [,attr2]...) | CLUSTER clustername }
[PCTFREE integer]
Durch die Angabe eines Tabellennamens und der zu indizierenden Attribute der Tabelle wird
ein mittelbarer Index auf der entsprechenden Relation aufgebaut. Durch Angabe von ASC
bzw. DESC wird das Attribut innerhalb des Index aufsteigend bzw. absteigend sortiert. 21
20
21
[18] Oracle – Datenbanken Administration und Management
[19] Datenbanksysteme
23
2.2.4.1 Index Cluster
Prinzip: Tupel mit gleichem Cluster Key werden gemeinsam in Blocken gespeichert.
•
Cluster Gruppe: Falls nicht alle zu einem Cluster-Key gehörenden Datensätze in einem
Datenblock Platz haben, werden die benötigten Blöcke zu einer Cluster Gruppe verkettet.
•
Je Länger die Cluster Gruppen sind desto geringer ist die Effizienz.
•
Cluster-Gruppen sollen auf nicht mehr als zwei DB-Blöcke verteilt sein.
•
Vorteile: Joins der am Cluster beteiligten Tabellen über Cluster key werden schneller (was bei
uns nicht der Fall war). Geringer Speicherbedarf, da Cluster Key nur einmal gespeichert wird.
•
Nachteil: Bei Abfragen, die nur eine Tabelle betreffen, sind mehr Zugriffe als bei
konventioneller Speicherung notwendig, da die Datensätze der Tabelle auf mehr Blöcke
verteilt sind.
•
Unterstützung: point-Queries und range-Queries.
24
2.2.4.1.1 Tests unter Oracle 10g XE
Getestet wurden zwei Tabellen:
• Part
• Partsupp
Bei den am Anfang durchgeführten Tests wurde es versucht erst ohne die Ermittlung des
Speicherbedarfs für Cluster zu arbeiten. So wurde eine Große von 512 Byte gewählt.
CREATE CLUSTER Cluster_Part_partsupp (p_partkey INTEGER ) size 512;
CREATE TABLE PARTSUPP ( P_PARTKEY
PS_SUPPKEY
PS_AVAILQTY
PS_SUPPLYCOST
PS_COMMENT
CLUSTER Cluster_Part_partsupp (P_PARTKEY);
INTEGER NOT NULL,
INTEGER NOT NULL,
INTEGER NOT NULL,
DECIMAL(15,2) NOT NULL,
VARCHAR(199) NOT NULL )
CREATE TABLE PART ( P_PARTKEY INTEGER NOT NULL,
P_NAME
VARCHAR(55) NOT NULL,
P_MFGR
CHAR(25) NOT NULL,
P_BRAND
CHAR(10) NOT NULL,
P_TYPE
VARCHAR(25) NOT NULL,
P_SIZE
INTEGER NOT NULL,
P_CONTAINER
CHAR(10) NOT NULL,
P_RETAILPRICE
DECIMAL(15,2) NOT NULL,
P_COMMENT
VARCHAR(23) NOT NULL )
CLUSTER Cluster_Part_partsupp (P_PARTKEY);
CREATE INDEX Part_partsupp_INDEX on CLUSTER Cluster_Part_partsupp;
Query 2 Zeit:
Mit Index Cluster: 3,48 seconds
Ohne Index Cluster: 0,89 seconds
Diese Tests haben gezeigt, dass leider mit dem Einsatz des Index Clusters die Laufzeit der Queries
sich verschlechtert hat. Was natürlich nicht der Fall sein sollte.
2.2.4.2 Hash Cluster
•
Einsatz: Wird verwendet, um einzelne Tabellen aber auch um mehrere Tabellen gemeinsam zu
speichern.
•
Vorteile: Extrem effizienter Zugriff über die Attributkombinationen auf die die Hashfunktion
angewendet wird (was leider bei uns nicht der Fall war). Es ist keine Suche im Index
notwendig.
•
Unterstützung: nur point-Queries.
Getestet wurden die gleichen Tabellen:
25
•
•
Part
Partsupp
CREATE CLUSTER Cluster_Part_partsupp (p_partkey INTEGER ) size 512, hash is p_partkey, HASHKEYS 200001
CREATE TABLE PARTSUPP ( P_PARTKEY INTEGER NOT NULL,
PS_SUPPKEY INTEGER NOT NULL,
…………………………………….
PS_COMMENT VARCHAR(199) NOT NULL )
CLUSTER Cluster_Part_partsupp (P_PARTKEY);
CREATE TABLE PART ( P_PARTKEY INTEGER NOT NULL,
P_NAME
VARCHAR(55) NOT NULL,
…………………………………………
P_COMMENT VARCHAR(23) NOT NULL )
CLUSTER Cluster_Part_partsupp (P_PARTKEY);
Query 2 Zeit:
Mit Index Cluster: 3,48 seconds
Ohne Index Cluster: 0,89 seconds
Mit Hash Cluster: 3,08 seconds
Diese Tests haben im Vergleich zu Index Cluster etwas besser abgeschnitten aber leider war das
Ergebnis trotzdem nicht gut.
2.2.4.3 Index Cluster mit SIZE = 800b
Weil die Optimierungsergebnisse nicht gut waren, wurde hier mit dem einfachen Weg versucht die
Größe des SIZE Parameters zu bestimmen.
Besonders vorteilhaft ist Index Cluster, wenn bei der 1:n Beziehung die Zahl n eine Konstante ist,
daher geclustert wurden noch einmal die gleichen Tabellen:
• Part
• Partsupp
Mit: select * from partsupp order by ps_partkey
wurde die Beziehung zu ps_partkey Schlüssel bestimmt. n war hier immer eine Konstante = 4.
26
Mit: Select table_name, avg_row_len from dba_tables
wurde die durchschnittliche Länge der PART und PARTSUPP Tabellen bestimmt.
Mit Hilfe der gelieferten Ergebnissen konnte man dann die Größe des SIZE Parameters errechnen:
|part|+n*|partsupp| ≈ 800 Byte
Die Ergebnisse waren besser aber trotzdem leider nicht gut.
2.2.4.4 Hash Cluster gegen Index Cluster
Die durchgeführten Tests unter Oracle 10g XE haben gezeigt, dass durch das Einsetzen der
CLUSTER die Laufzeit der Queries sich veschlechtert hat. Auch das Ermitteln der Größe für SIZE
Parameter hat zu keinen besseren Ergebnissen geführt.
2.2.4.5 Tests unter Oracle 10g EE
Wie die folgende Graphische Darstellung zeigt, dass nachdem die Optimierung mit Hilfe der Tabellen
Partitionierung durchgeführt wurde, hat die Laufzeit der Queries sich merklich verbessert, trotzdem
blieb die Laufzeit der Queries 18 und 21 außerhalb der Verbesserung.
Daher wird im Folgenden die Optimierung mit Hilfe der Index und Hash Cluster durchgeführt und die
Laufzeit während der Optimierung wird nur bei diesen beiden Queries betrachtet.
27
2.2.4.6 Ermittlung des Speicherbedarfs für Cluster
Sowohl bei Indexclustern als auch bei Hash – Clustern ist es wichtig, den Platzbedarf für die Daten
abzuschätzen.
Das im folgenden dargestellter Verfahren zeigt, wie sich der anfängliche Speicherbedarf für eine
geclusterte Menge von Tabellen abschätzen lässt. Dieses Verfahren schätzt ausschließlich den
anfänglichen Speicherbedarf ab.
Zum Abschätzen des Speicherbedarfs von Clustern sind folgende Schritte auszuführen:
Schritt 1: Berechnung der Gesamtgröße des Block-Headers und des für Tabellendaten verfügbaren
Speicherplatzes.
Schritt 2: Berechnung des Platzbedarfs pro Zeile.
Schritt 3: Berechnung der gesamten durchschnittlichen Zeilengröße.
Schritt 4: Berechnung der durchschnittlichen Blockgröße für den Cluster.
Schritt: 1 Berechnung der Gesamtgröße des Block-Headers und des für Tabellendaten
verfügbaren Speicherplatzes.
Die folgende Formel liefert als Ergebnis die Menge des in einem Block zur Verfügung stehenden
Speicherplatzes:
Platz im Block nach Abzug der Header (Platz ohne Header) =
DB_BLOCK_SIZE - (KCBH - UB4 - KTBBH - ((INITRANS – 1) * KTBIT – KDBH)
Wert erhält man aus der Data Dictionary Tabelle V$PARAMETER
SELECT value FROM v$parameter WHERE name = 'db_block_size';
Value = 8192 Byte (8 KByte)
DB_BLOCK_SIZE
KCBH, UB4, KTBBH, KTBIT, KDBH
Werte erhält man aus der Data Dictionary Tabelle V$TYPE_SIZE
select * from v$type_size;
KCBH
UB4
KTBBH
KTBIT
KDBH
BLOCK COMMON HEADER
UNSIGNED BYTE
TRANSACTION FIXED HEADER
TRANSACTION VARIABLE HEADER
DATA HEADER
20 Byte
4 Byte
48 Byte
24 Byte
14 Byte
Wert gibt Auskunft darüber, wie viele Transaktionen simultan einen Datenblock updaten
können. Dieser Wert ist natürlich abhängig von der Anzahl der User, die gleichzeitig auf einen Block
(auf eine Tabelle) zugreifen könnten. Jeder Eintrag für eine Transaktion, die gerade auf einen Block
zugreift belegt 24 Bytes freien Speicher des Blockes. Bei der Erstellung eines Indexes, bzw. einer
Tabelle wird gleichzeitig auch der INITRANS Wert festgelegt. Default 1 für Tabellen, 2 für Indizes.
INITRANS
Mit einer Blockgröße von 8 KByte und dem INITRANS – Wer 1 ergibt sich folgende Rechnung:
8192 – 20 – 4 – 48 – (24 * (1-1)) – 14 = 8106 Byte
Schritt 2: Berechnung des Platzbedarfs pro Zeile
Zur Berechnung dieses Wertes muss man auf folgendes achten:
Platzbedarf muss anhand einer durchschnittlichen Zeile für jede Tabelle im Cluster berechnet werden.
Angenommen uns liegen die beiden geclusterten Tabellen vor:
28
CREATE TABLE ORDERS
(L_ORDERKEY
NUMBER (10, 2) NOT NULL,
O_CUSTKEY
NUMBER (10, 2) NOT NULL,
O_ORDERSTATUS
CHAR(1) NOT NULL,
O_TOTALPRICE
NUMBER (15, 2) NOT NULL,
O_ORDERDATE
DATE NOT NULL,
O_ORDERPRIORITY
CHAR(15) NOT NULL,
O_CLERK
CHAR(15) NOT NULL,
O_SHIPPRIORITY
NUMBER (10, 2) NOT NULL,
O_COMMENT
VARCHAR (79) NOT NULL)
CLUSTER Cluster_ORDERS_LINEITEM (L_ORDERKEY);
CREATE TABLE LINEITEM
(L_ORDERKEY
NUMBER (10, 2) NOT NULL,
L_PARTKEY
NUMBER (10, 2) NOT NULL,
L_SUPPKEY
NUMBER (10, 2) NOT NULL,
L_LINENUMBER
NUMBER (10, 2) NOT NULL,
L_QUANTITY
NUMBER (15, 2) NOT NULL,
L_EXTENDEDPRICE
NUMBER (15, 2) NOT NULL,
L_DISCOUNT
NUMBER (15, 2) NOT NULL,
L_TAX
NUMBER (15, 2) NOT NULL,
L_RETURNFLAG
CHAR(1) NOT NULL,
L_LINESTATUS
CHAR(1) NOT NULL,
L_SHIPDATE
DATE NOT NULL,
L_COMMITDATE
DATE NOT NULL,
L_RECEIPTDATE
DATE NOT NULL,
L_SHIPINSTRUCT
CHAR (25) NOT NULL,
L_SHIPMODE
CHAR (10) NOT NULL,
L_COMMENT
VARCHAR (44) NOT NULL)
CLUSTER Cluster_ORDERS_LINEITEM (L_ORDERKEY);
Clusterschlüssel in jeder Tabelle ist L_ORDERKEY.
Es ergeben sich zwei folgende Rechnungen:
D1 (TABLE LINEITEM) = (a + b + c + d + e + f + g + j + h + I + k + l + m) Byte = 10 + 10 + 10 + 10 + 15
+ 15 + 15 + 15 + 25 + 10 + 44 = 179 Byte
D2 (TABLE ORDERS) = (n + p + o + q + r + s + t + v) Byte = 10 + 10 + 1 + 15 + 15 + 15 + 10 + 79 = 155
Byte
Schritt 3: Berechnung der gesamten durchschnittlichen Zeilengröße.
Man kann den in einer geclusterten Tabelle mindestens für eine Zeile benötigten Platz mit folgender
Gleichung berechnen:
Sn Byte / Zeile = Zeilen – Header + Fn + Vn + Dn
Dabei gilt:
Zeilen – Header: Vier Byte pro Zeile einer geclusterten Tabelle.
Fn: Gesamtanzahl der Längenbytes für Spalten der Tabelle n mit einer Länge von 250 oder weniger
Byte. Für jede derartige Spalte wird 1 Längenbyte veranschlagt.
Vn: Gesamtanzahl der Längenbytes für Spalten der Tabelle n, in denen mehr als 250 Byte gespeichert
werden. Für jede derartige Spalte werden 3 Längenbytes veranschlagt.
Dn: Kombinierter Platz für Daten aller Spalten in Tabelle n (aus Schritt 2).
Demnach ergibt sich beispielsweise die gesamte durchschnittliche Zeilengröße für die geclusterten
Tabellen LINEITEM und ORDERS wie folgt:
S1 = (4 + (1 * 13) + (3 * 0) + 179) = 196 Byte
29
S2 = (4 + (1 * 8) + (3 * 0) + 155) = 167 Byte
Schritt 4: Berechnung der durchschnittlichen Blockgröße für den Cluster.
Zum Berechnen der durchschnittlichen Blockgröße des Clusters muss man zunächst die
durchschnittliche Anzahl von Zeilen (für alle Tabellen) pro Clusterschlüssel ermitteln. Sobald dieser
Wert bekannt ist, kann folgenden Gleichung benutzt werden, um die durchschnittliche Blockgröße für
den Cluster zu berechnen:
Durchschn.Cluster – Blockgröße (Byte) = ((R1 * S1) + (R2 * S2) + … + ( Rn * Sn)) + Schlüssel –
Header + Ck + Sk + 2Rt.
Dabei gilt:
Rn: Die durchschnittliche Anzahl von Zeilen in Tabelle n, die einem Clusterschlüssel zugeordnet sind.
(select * from lineitem order by l_orderkey)
Sn: Die durchschnittliche Zeilengröße in Tabelle n (aus Schritt 3).
Schlüssel – Header: Hat den Wert 19.
Ck: Die Spaltengröße für den Clusterschlüssel.
Sk: Der zum Speichern eines durchschnittlichen Clusterschlüssels benötigte Platz.
Rt: Die Gesamtanzahl der Zeilen, die einem durchschnittlichen Clusterschlüssel (R1 + R2 + … + Rn)
zugeordnet sind. Daraus ergibt sich der für jede Zeile des Blocks im Header des Datenblocks benötigte
Platz.
Als Beispiel wurden wieder die Tabellen LINEITEM und ORDERS genommen. Ein durchschnittlicher
Clusterschlüssel verfügt über 4 Zeilen pro Tabelle LINEITEM und über 1 pro Tabelle ORDERS. Des
weiternen ist der Clusterschlüssel von Datentyp NUMBER (Spaltengröße = 1 Byte) und die Zahl
besteht durchschnittlich aus 6 Ziffern (5 Byte). Mit diesen Werten und den vorangegangenen
Ergebnissen ergibt sich die durchschnittliche Größe für den Clusterschlüssel wie folgt:
Größe = ((3 * 196) + (1 * 167) + 19 + 1 + 5 + (2 * 4)) Byte = 788 Byte
Diese ermittelte Größe kann in der SIZE – Klausel angegeben werden, wenn man die Cluster mit Hilfe
des CREATE CLUSTER – Befehls erstellt. Dieser Wert gibt an, wie viel Platz benötigt wird, um einen
durchschnittlichen Clusterschlüssel und die ihm zugeordneten Zeilen aufzunehmen; Oracle verwendet
diesen Wert, um die Anzahl der Clusterschlüssel zu beschränken, die sich einem gegebenen
Datenblock zuordnen lassen. 22
2.2.4.7 Tests unter Oracle 10g EE mit Index Cluster
Hier wird es versucht Index Cluster unter Tabellen
benutzen:
LINEIETEM, ORDERS
und
NATION, SUPPLIER
zu
CREATE CLUSTER Cluster_ORDERS_LINEITEM (L_ORDERKEY NUMBER (10, 2)) size 788;
Als nächstes werden die beiden geclusterten Tabellen LINEIETEM und ORDERS erstellt und zum Schluss
wird auf dem CLUSTER Cluster_ORDERS_LINEITEM eine INDEX ORDERS_LINEITEM_INDEX erstellt.
CREATE INDEX ORDERS_LINEITEM_INDEX on CLUSTER Cluster_ORDERS_LINEITEM;
________________________
22
[18] Oracle – Datenbanken Administration und Management
30
CREATE CLUSTER Cluster_SUPPLIER_NATION (S_NATIONKEY NUMBER (10, 2)) size 902;
CREATE TABLE SUPPLIER ( S_SUPPKEY
NUMBER (10, 2) NOT NULL,
S_NAME
CHAR(25) NOT NULL,
S_ADDRESS
VARCHAR(40) NOT NULL,
S_NATIONKEY
NUMBER (10, 2) NOT NULL,
S_PHONE
CHAR(15) NOT NULL,
S_ACCTBAL
NUMBER (10, 2) NOT NULL,
S_COMMENT
VARCHAR (101) NOT NULL)
CLUSTER Cluster_SUPPLIER_NATION (S_NATIONKEY);
CREATE TABLE NATION (
S_NATIONKEY
NUMBER (10, 2) NOT NULL,
N_NAME
CHAR(25) NOT NULL,
N_REGIONKEY
NUMBER (10, 2) NOT NULL,
N_COMMENT
VARCHAR(152))
CLUSTER Cluster_SUPPLIER_NATION ( S_NATIONKEY);
CREATE INDEX SUPPLIER_NATION_INDEX on CLUSTER Cluster_SUPPLIER_NATION;
Die Graphische Darstellung zeigt, dass die durchgeführten Tests mit Index Cluster unter Oracle 10g
EE erfolgreich waren. Die beiden Queries haben sich im Vergleich zur Optimierung mit RANGE
Partitionierung erheblich verbessert, insbesondere die Query 21 lief anstatt 2,1 Minuten nur noch 0,59
Sekunden.
2.2.4.8 Tests unter Oracle 10g EE mit Hash Cluster
Wie bei Indexclustern ist auch bei Hash – Clustern wichtig, den Platzbedarf für die Daten
abzuschätzen. Aber im Unterschied zu Index Cluster muss man hier folgendes beachten:
• Für Hash – Cluster besteht das Teilziel darin, die Größe für jeden Hash – Cluster zu ermitteln.
Daher muss man nicht nur die Anzahl von Zeilen pro Clusterschlüsselwert, sondern auch die
Verteilung der Clusterschlüssel über die Hash – Schlüssel im Cluster berücksichtigen.
•
Anders als beim Indexcluster wird der Clusterschlüsselwert mit jeder Zeile gespeichert, die
sich in einem Hash – Cluster befindet.
•
Im Schritt 4 muss man auf die Addition des Platzbedarfs für den Clusterschlüsselwert (Ck)
verzichten. Weil dieser Wert bereits im Schritt 3 berücksichtigt wurde. 23
Hier wird es gezeigt wie SIZE Parameter unter Hash Cluster anhand des Beispiels mit den Tabellen
PARTSUPP und LINEITEM ermittelt werden kann:
23
[18] Oracle – Datenbanken Administration und Management
31
Schritt 2:
D1 (TABLE LINEITEM) = (a + b + c + d + e + f + g + j + h + I + k + l + m) Byte = 10 + 10 + 10 + 10 + 15
+ 15 + 15 + 15 + 25 + 10 + 44 = 179 Byte
D2 (TABLE ORDERS) = (n + p + o + q + r + s + t + v) Byte = 10 + 10 + 1 + 15 + 15 + 15 + 10 + 79 = 155
Byte
Schritt 3:
S1 = (4 + (1 * 13) + (3 * 0) + 179 + 1) = 197 Byte
S2 = (4 + (1 * 8) + (3 * 0) + 155 + 1) = 168 Byte
Schritt 4:
Ein durchschnittlicher Clusterschlüssel verfügt über 4 Zeilen pro Tabelle LINEITEM und über 1
Tabelle ORDERS. Des weiternen ist der Clusterschlüssel von Datentyp NUMBER (Spaltengröße
Byte) und die Zahl besteht durchschnittlich aus 6 Ziffern (5 Byte). Mit diesen Werten und
vorangegangenen Ergebnissen ergibt sich die durchschnittliche Größe für den Clusterschlüssel
folgt:
pro
=1
den
wie
Größe = ((3 * 197) + (1 * 168) + 19 + 5 + (2 * 4)) Byte = 791 Byte
__________________________________________________________________________
CREATE CLUSTER Cluster_ORDERS_LINEITEM (L_ORDERKEY NUMBER (10, 0)) size 791, hash is L_ORDERKEY, HASHKEYS
200001;
Als nächstes warden die beiden geclusterten Tabellen LINEIETEM und ORDERS erstellt.
CREATE TABLE ORDERS ( …)
CLUSTER Cluster_ORDERS_LINEITEM (L_ORDERKEY);
CREATE TABLE LINEITEM (…)
CLUSTER Cluster_ORDERS_LINEITEM (L_ORDERKEY);
____________________________________________________________________
CREATE CLUSTER Cluster_SUPPLIER_NATION (S_NATIONKEY NUMBER (10, 0)) size 905, hash is S_NATIONKEY, HASHKEYS
31;
CREATE TABLE SUPPLIER (…)
CLUSTER Cluster_SUPPLIER_NATION (S_NATIONKEY);
CREATE TABLE NATION (…)
CLUSTER Cluster_SUPPLIER_NATION ( S_NATIONKEY);
Die folgende Graphische Darstellung zeigt, dass im Unterschied zur Oracle 10g XE hat durch den
Einsatz der Cluster unter Oracle 10gEE die Laufzeit der Queires sich verbessert. Wobei die Query 18
war langsamer unter Index Cluster und schneller unter Hash Cluster und Query 21 war genau
umgekehrt.
32
2.2.4.9 Weitere Tests
Als nächstes wurde versucht zu testen, wie gut oder schlecht die Ergebnisse unter Oracle 10g EE sind,
wenn man mit den gleichen Queries arbeitet und die gleichen Optimierungsmaßnahmen durchführt
wie bei Oracle 10g XE im Bezug auf Cluster.
Wie bei Oracle 10g XE auch bei Oracle 10g EE wurden zwei Tabellen:
• Part
• Partsupp
getestet.
•
•
•
•
Mit INDEX CLUSTER wobei SIZE = 512 Byte (alle Queries wurden getestet).
Mit HASH CLUSTER wobei SIZE = 512 Byte (alle Queires wurden getestet).
Mit INDEX CLUSTER wobei SIZE = 800 Byte (nur Queires 2 und 16 wurden getestet).
Zum Schluss wurden Tests auf zwei Queries mit Turning Pack durchgeführt. Die Queires 2
und 16 sind die fast einzigen Queries, die den CLUSTER der PART und PARTSUPP Tabellen
benutzen, daher wurden nur die beiden bei Tuning Pack Test benutzt.
Diese Abbildung zeigt, dass im Unterschied zur Oracle 10g XE, verbessert sich die Laufzeit der
Queries unter Oracle 10g EE merklich, wobei INDEX CLUSTER mit SIZE = 512 etwas besser abgeschnitten
hat als HASH CLUSTER mit SIZE = 512, und etwas schlechter als INDEX CLUSTER mit dem errechneten SIZE
Parameter = 800 was zeigt, dass es bei der Arbeit mit dem Cluster wichtig ist den SIZE Parameter
richtig zu berechnen.
Am Besten waren die Ergebnisse nachdem das Oracle Tuning Pack benutzt wurde, was in der
Graphischen Darstellung von Oben deutlich zu sehen ist.
Als nächstes ist der Ausführungsplan des Oracle Tuning Packs für Query 2 unter dem Einsatz des
INDEX CLUSTER zu sehen.
.
33
Dieser Ausführungsplan der Oracle Tuning Packs gibt die Empfehlungen wie man die Laufzeit der
Query beschleunigen kann.
Hier zeigt der Optimierer die Query Ausführungspläne vor der Benutzung und nach der Benutzung des
Oracle Tuning Packs.
Führt man die Vorschläge durch so verbessert sich die Laufzeit der Query von 0,02 auf 0,01
Sekunden.
Das Ergebnis der Optimierung mit dem Oracle Tuning Pack für Query 16 war noch besser, hier
verbesserte sich die Laufzeit von 0,22 auf 0,15 Sekunden.
2.2.4.10 FAZIT
Die durchgeführten Tests unter Oracle 10g XE und Oracle 10g EE im Bezug auf CLUSTER zeigten, dass
es etwas schwer ist mit den CLUSTER zu arbeiten, weil man sehr darauf achten muss den SIZE
Parameter richtig auszuwählen. Außerdem unter Oracle 10g XE sollte man auf die Arbeit mit den
CLUSTER versuchen zu verzichten, weil die Laufzeit der Queries während den Tests sich sofort
verschlechterte, was aber nicht der Fall unter Oracle 10g EE war, hier haben die gleichen Tests zu den
guten Ergebnissen geführt wenn man die CLUSTER benutzte.
34
Am Besten waren die Ergebnisse nachdem das Oracle Tuning Pack benutzt wurde. Wird aber leider
nur unter Oracle 10g EE angeboten. Näher über Oracle Tuning Pack wird in dem letzten Kapitel
diskutiert.
2.2.5 Optimale Indexierung von Tabellen
In den meisten Fällen ist eine indizierte Suche schneller als ein normaler Tabellendurchlauf dann,
wenn die Tabelle mehr als 500 Zeilen enthält. Oracle unterstützt eine Reihe von Indizes wie B-Tree,
bitmap sowie die Erstellung von Index organisierten und geklusterten Tabellen (Index Cluster oder
Hash Cluster).
Obwohl die Indizes und die Primärschlüssel kein Muss für eine Tabelle sind, ist mindestens ein
Primärschlüssel empfohlen. Die Indizierung muss den Ausführungsplänen der Anfragen entsprechen.
Da die Indizes die Update-Operationen verlangsamen, sind sie nur für die Spalten geeignet, die in
Anfragen und Berichten verwendet werden.
2.2.5.1 B-Tree Indexes - Primärschlüssel
Die Unterschiede zwischen einem Primärschlüssel und einem UNIQUE-Schlüssel in Oracle sind:
• Eine Tabelle kann maximal ein Primärschlüssel, aber kann mehrere Unique-Indizes für
verschiedene Spalten haben
• Ein Primärschlüssel erzwingt eine NOT NULL Constraint auf die entsprechenden Spalten,
aber ein Index nicht. Man kann nur eine Zeile hinzufügen oder ändern, der den Wert NULL
für die Unique-Spalten zugewiesen ist.
Zuerst wurden die Queries ohne Primärschlüssel ausgeführt und danach mit, um zu sehen, ob die
Indexes, die Oracle automatisch bei der Deklaration der Primärschlüssel erstellt, nützlich sind.
Die Ergebnisse sind in der folgenden Abbildung zu sehen:
DB ohne und mit PK
17:16.8
14:24.0
Zeit
11:31.2
08:38.4
05:45.6
02:52.8
Q22
Q21
Q20
Q19
Q18
Q17
Q16
Q15
Q14
Q13
Q12
Q11
Q9
Q10
Q8
Q7
Q6
Q5
Q4
Q3
Q2
Q1
00:00.0
Queries
DB ohne
und Primärschlüssel
mit PK
Verbesserung/Verschlechterung der Ausführungszeiten nach dem Erstellen
von
Prozent Verbesserung PK
17:16.8
100.00%EE +5,29%), aber in vielen Fällen ist es
In allgemeinen war es besser (Oracle XE + 15%, Oracle
14:24.0
schlechter geworden.
80.00%
60.00%
08:38.4
40.00%
Zeit
Query 2 war besonders interessant (+97,8% besser).
Die Ausführungsplan:
Zeit
11:31.2
05:45.6
Series1
20.00%
02:52.8
Queries
-40.00%
Queries
35
Q22
Q21
Q20
Q19
Q17
Q
2
Q18 1
Q15
Q
Q16 19
7
Q14Q 1
Q12Q
1
Q13 5
Q10
Q
Q11 13
11
Q8
Q9Q
9
Q
Q7
Q6 7
Q
Q5
Q4 Q 5
Q3
Q2 Q
Q
Q1 1
3
0.00%
00:00.0
-20.00%
Ausführungsplan der Anfrage Q2 ohne und mit Primärschlüssel
Die Erklärung ist es, statt full table access auf den Tabellen partsupp, nation, region wurden sehr
effizient die erstellten Indexes benützt um die Anfrage zu beschleunigen.
Bei der Anfrage Q10 sind sowohl bei Oracle XE, als auch bei Oracle EE höhere Zeiten aufgetreten.
Wenn man den Ausführungsplan schaut, kann man sehen, dass der Optimizer gar keinen Index benützt
hat, als ob es keine Primärschlüssel gegeben hätte. Wir gehen davon aus, die Zeiten wurden von
anderen Faktoren beeinflusst (z.B. Servicezeiten).
Ausführungspläne für Q10 ohne und mit Primärschlüssel
2.2.5.2 B-Tree Indexes - Einfache Indexes
Für alle Tabellen wurden entsprechend Indexes auf je einer Spalte gesetzt, so wie Oracle Tuning Tool
empfiehlt. Alle diese Indexe wurden in einer anderen Tablespace erstellt, um ihre Manipulation zu
vereinfachen. Die Zeiten wurden gemessen und die Ergebnisse sind abgebildet:
36
CREATE TABLESPACE idx_einfach DATAFILE
'C:\oracle\product\10.2.0\oradata\tpch\idx_einfach.dbf' SIZE 1M
AUTOEXTEND ON NEXT 500k;
***Q1***
create index i_l_shipdate on lineitem (l_shipdate) tablespace idx_einfach;
***Q2***
create index i_r_name on region (r_name) tablespace idx_einfach;
***Q3***
create index i_c_mktsegment on customer(c_mktsegment) tablespace
idx_einfach;
create index i_o_orderdate on orders (o_orderdate) tablespace idx_einfach;
***Q4***
create index i_l_commitdate on lineitem(l_commitdate) tablespace
idx_einfach;
create index i_l_receiptdate on lineitem(l_receiptdate) tablespace
idx_einfach;
***Q5***
***hat alle Indexes
***Q6***
create index i_l_quantity on lineitem(l_quantity) tablespace idx_einfach;
create index i_l_discount on lineitem(l_discount) tablespace idx_einfach;
***Q7***
create index i_n_name on nation (n_name) tablespace idx_einfach;
***Q8***
create index i_p_type on part(p_type) tablespace idx_einfach;
***Q9***
create index i_p_name on part(p_name) tablespace idx_einfach;
***Q10***
create index i_l_returnflag on lineitem(l_returnflag) tablespace
idx_einfach;
***Q11***
***hat alle Indexes
***Q12***
create index i_l_shipmode on lineitem(l_shipmode) tablespace idx_einfach;
Erklärungen Einfache Indexes.
***Q13***
create index i_o_comment on orders(o_comment) tablespace idx_einfach;
Einfache Indexes
08:38.4
07:12.0
Zeit
05:45.6
04:19.2
02:52.8
01:26.4
Que rie s
Nur PK
Ausführungszeiten für einfache Indexes bei Oracle XE und Oracle EE
37
Einfache Indexes
Q22
Q21
Q20
Q19
Q18
Q17
Q16
Q15
Q14
Q13
Q12
Q11
Q9
Q10
Q8
Q7
Q6
Q5
Q4
Q3
Q2
Q1
00:00.0
Während bei Oracle XE das eine schlechte Idee war (Zeit um 5% schlimmer), scheint es bei Oracle EE
eine relativ gute Idee zu sein (Zeit um 6% besser).
Wir wollen jetzt den Ausführungsplan der Query 10 sehen. Im Oracle EE sieht es so aus:
Ausführungsplan für Q10 mit einfachen Indexes
Man bemerkt, es wurde nur ein einfacher Index benützt. Es gibt leider 3 full table access Operationen,
die die Anfrage sehr langsam machen. Wir wollen jetzt sehen, ob uns das Tuning Tool eine gute Idee
gibt:
Leider nicht. /
Wenn wir den Ausführungsplan der Query 8 analysieren, sehen wir, dass viele Indexe benützt wurden,
und man sollte eigentlich eine bessere Zeit erhalten.
Ausführungsplan der Anfrage Q8 ohne und mit einfachen Indexen in Oracle XE
38
Ausführungsplan der Query 8 mit einfachen Indexes in Oracle EE
Wir wollen wieder sehen, ob man etwas verbessern kann und bitten um eine Empfehlung. Die sieht so
aus:
Empfehlung für die Verbesserung der Ausführungszeit von Q8
Er sagt also, neue Indexes wären nötig und schlagt einen neuen Ausführungsplan vor:
Der vorgeschlagene Plan und der alten Plan der Q8
Wir wollen die Empfehlung implementieren und drücken auf
.
Nach der Erstellung der neuen Indexes ist die Ausführungszeit 02:53,87 geworden und früher war
02:51,0. Wir sind also enttäuscht, die Zeit hat sich nicht verbessert, wie versprochen.
2.2.5.3 B-Tree Indexes - Mehrspalten Indexes
Man sagt, dass ein mehrspaltig verketteter Index performanter als mehrere separate einspaltige Indizes
ist. Um diese Aussage zu überprüfen, wurden solche Indexes erstellt und die Zeiten wieder gemessen.
Die erste Spalte eines verketteten Indices sollte in den WHERE Klausel der Anfragen verwendet werden.
Damit die indizierte Suche effizient ist, soll die erste Spalte eine hohe Selektivität haben. Die
39
zweitmeistens verwendete Spalte sollte die zweitgrößte Selektivität haben und die zweite in einem
verkettetem Index sein usw. Die Selektivität der ersten Spalte eines veketteten Indizes besimmt die
Selektivität des ganzen Indizes, deshalb soll sie möglichst hoch sein.
Die Selektivität eines Spaltensets von einer Tabelle ist das Bezugsverhältnis m/n, wo
m = Kardinalität des Sets (Anzahl unterschiedliche Werten),
n = Gesamtanzahl der Zeilen in der Tabelle.
Die Selektivität eines Spaltensets meßt die Nützlichkeit des Sets in der Reduzierung der I/O
Operationen bei den Anfragen, die das Set verwenden. Der maximale Wert der Selektivität ist 1 wenn
alle Zeilen unterschiedlich sind, so dass m = n (z. B. die Primärschlüssel-Spalten). Die indizierten
Spalten müssen eine hohe Selektivität haben.
Für diese Indices legen wir zunächst einen neuen Tablespace an:
CREATE TABLESPACE idx_mehr DATAFILE
'C:\oracle\product\10.2.0\oradata\tpch\idx_mehr.dbf' SIZE 1M
AUTOEXTEND ON NEXT 500k;
CREATE INDEX im1_lineitem ON lineitem (l_shipdate, l_returnflag,
l_linestatus) TABLESPACE idx_mehr;
CREATE INDEX im2_lineitem ON lineitem (l_returnflag, l_linestatus,
l_shipdate) TABLESPACE idx_mehr;
CREATE INDEX im_p_size_type ON part (p_size, p_type) TABLESPACE idx_mehr;
CREATE INDEX im1_supplier ON supplier (s_acctbal desc, s_name) TABLESPACE
idx_mehr;
CREATE INDEX im2_supplier ON supplier (s_suppkey, s_name, s_address,
s_phone) TABLESPACE idx_mehr;
CREATE INDEX im3_supplier ON supplier (s_comment, s_suppkey) TABLESPACE
idx_mehr;
CREATE INDEX im3_lineitem ON lineitem (l_shipdate, l_partkey,
l_extendedprice, l_discount) TABLESPACE idx_mehr;
Die Ausführungszeiten:
Mehrspalten Index
05:45.6
05:02.4
04:19.2
Zeit
03:36.0
02:52.8
02:09.6
01:26.4
00:43.2
00:00.0
Q1
Q2
Q13
Q15
Q16
Q17
Q18
Q19
Que rie s
Nur PK
M ehrere Spalten Indexes
Ausführungszeiten für mehrspaltigen Indexes bei Oracle XE und Oracle EE
Hier ist es wieder etwas Interessantes passiert: während das Ergebnis bei Oracle XE schlechter war
(um 17%), haben die Mehrspalten-Indexes gute Ergebnisse bei Oracle EE gezeigt (um 19%).
40
Wir analysieren den Ausführungsplan der Q18 und die Konklusion ist, dass die Benützung der
mehrspaltigen Index i2_part ein bisschen besser war, als full table access auf der Tabelle Part. Der
kleine 2,8% Unterschied wird durch externe Faktoren erklärt.
Ausführungspläne der Q18 vor und nach der Erstallung der mehrspaltigen Indexes
B-Tree Indexes: Fat Indexes (3Sterne)
Ein FAT Index ist ein Index, der mindestens den dritten Stern hat. Er beinhaltet alle Spalten von der
SELECT-Anweisung und besorgt für index access only. Er ist der best-mögliche Index für eine Oracle
Anfrage.
Um für den ersten Stern sich zu qualifizieren, muss ein Index alle Spalten von der WHERE-Klausel
beinhalten. Die sollen am Anfang im Index sich befinden.
Um für den zweiten Stern sich zu qualifizieren, müssen sie die Spalten von ORDER BY haben.
Wenn der Index auch den Rest der Spalten von der SELECT-Anweisung hat, dann bekommt er auch
den dritten Stern.
Es wurden mehreren FAT Indexes erstellt, die von mehreren Anfragen benützt werden:
CREATE TABLESPACE idx_fat DATAFILE
'C:\oracle\product\10.2.0\oradata\tpch\idx_fat.dbf' SIZE 1M
AUTOEXTEND ON NEXT 500k;
CREATE INDEX fi ON lineitem(l_returnflag, l_linestatus, l_shipdate,
l_quantity, l_extendedprice, l_discount, l_tax) TABLESPACE idx_fat;
CREATE INDEX fi2 ON lineitem(l_shipdate, l_returnflag, l_linestatus,
l_discount, l_quantity, l_extendedprice, l_tax) TABLESPACE idx_fat;
CREATE INDEX i3_lineitem ON lineitem(l_shipdate, l_partkey,
l_extendedprice, l_discount) TABLESPACE idx_fat;
CREATE INDEX i3_part ON part(p_brand, p_container, p_size, p_partkey)
TABLESPACE idx_fat;
CREATE INDEX i4_part ON part(p_partkey, p_brand, p_container, p_size)
TABLESPACE idx_fat;
41
Die Ergebnisse sind ausgezeichnet bei Oracle XE und auch bei Oracle EE:
FAT Indexes Effektivität
03:36,0
Zeit
02:52,8
02:09,6
01:26,4
00:43,2
00:00,0
Q6
Q14
Q19
Queries
nur PK
FAT
FAT Indexes Verbesserung bei Oracle XE und EE
Während bei Oracle XE eine 99% Verbesserung zu sehen war, war bei Oracle EE nur 77%, aber noch
sehr gut.
Die Ordnung der Spalten im Index ist sehr wichtig und bestimmt die Ausführungszeit.
Ein Plan einer Anfrage mit FAT Index ist in der Abbildung 2.13.
Ausführungsplan der Query 14 mit FAT Index
2.2.5.4 Index organisierte Tabellen (IOT)
Tabellen können als Index Organized Table verwaltet werden. Dies spart den zusätzlichen Index für
den Primary Key. Insbesondere bei Tabellen mit wenigen Spalten sollte ein Einsatz in Betracht
gezogen werden.
Eine Index organisierte Tabelle sieht ähnlich wie eine normale Tabelle mit einem B*-tree Index für die
Primärschlüssel. Der Unterschied ist, dass bei Index organisierte Tabellen hält Oracle in einer einzigen
B*-tree Struktur sowohl die Primärschlüssel, als auch die anderen Spaltenwerte für jede Zeile. Die
Grundtabelle entfällt. Die Vorteile sind, dass diese Tabellen weniger Speicher verbrauchen und
schneller primärschlüsselbasierter Zugriff für eine Reihe von Anfragen sichern. Zusätzlich sind die
INSERTS, DELETES und UPDATES ein bisschen schneller, weil es eine Seite weniger zu ändern
42
gibt. Die Zeilen der Tabellen haben keine ROWID; ihre Ordnung ist von den Primärschlüssel gegeben.
Man kann keinen zweiten Index auf eine solche Tabelle anlegen.
Der Speicher ist für eine Index organisierte Tabelle in zwei Bereichen verteilt: Index und Overflow.
Der Index-Teil ist in einem Index Tablespace gespeichert und der Overflow Teil in einem separaten
Daten Tablespace. Die Trennung der Zeilen der Tabelle in den zwei Tablespaces kann in der CREATE
TABLE Anweisung festgelegt werden:
• PCTTHRESHHOLD p, mit p Ganzzahl, 0 ≤ p ≤ 50 und
• INCLUDING column_name, wo column_name eine Spalte der Tabelle ist.
Für einen bestimmten p-Wert liefert PCTTHRESHOLD das Equivalent von p% der Größe des
Datenblocks der Datenbank.
Im Vergleich zu den anderen Indexes, weisen die IOTs auch Nachteile, wie zum Beispiel manchmal
mehreren I/Os.
Index organisierte Tabellen können bei vielen Änderungen stark fragmentieren. Eine Online
Reorganisation ist nur mit dem Paket dbms_redefinition möglich.
Die Variable rowlength soll nicht zu lang sein. Wir suchen eine Tabelle, die die Zelen kurz hat:
SELECT table name, avg row len FROm dba tables ORDER BY avg row len ASC
Orders. Wir legen eine neue, Index organisierte Orders-Tabelle an:
CREATE TABLE orders2 (o_orderkey INTEGER NOT NULL, o_custkey INTEGER NOT
NULL, o_orderstatus CHAR(1) NOT NULL, o_totalprice DECIMAL(15,2) NOT
NULL, o_orderdate DATE NOT NULL, o_orderpriority CHAR(15) NOT NULL,
o_clerk CHAR(15) NOT NULL, o_shippriority INTEGER NOT NULL, o_comment
VARCHAR(79) NOT NULL, CONSTRAINT pk_o2 PRIMARY KEY(o_orderkey))
ORGANIZATION
INDEX
Und
führen die Queries
aus, die einen Join mit dieser Tabelle machen. Ergebnisse:
TABLESPACE idx_fat;
INSERT INTO orders2 SELECT * FROM orders;
IOT
04:19,2
03:36,0
Zeit
02:52,8
02:09,6
01:26,4
00:43,2
00:00,0
Q3
Q4
Q8
Q12
Queries
nur PK
IOT
IOT bei Oracle XE und EE
Bei Oracle EE war eine durchschnittliche Verschlechterung der Zeit um 48,8%, ung. gleichmäßig bei
allen Indexes. Bei der XE hatte die IOT Orders einen sehr schlechten Benehmen (199%), aber als die
IOT Tabelle Linitem2 angelegt wurde, war die Verbesserung 14%.
43
Ausführungsplan der Query 3 mit IOT
2.2.5.5 Bitmapped Index und Bitmapped Join Index
B*- tree Indexes sind für Spalten mit geringe Selektivität nicht geeignet. Oracle empfiehlt für die
Queries, die mehr als 15% der Zeilen zurückliefern, eine „full scan“ zu verwenden. Für solche
Zwecken hat Oracle seit der Version 7.3 die Bitmap Indexes eingeführt. Ein Bitmap Index passt in den
nächsten Situationen:
• Die Spalte hat eine geringe Selektivität
• Die Tabelle ist selten aktualisiert
• Die Tabelle ist sehr groß (mindestens 500.000 Einträge)
• Die Anfrage enthält eine oder mehrere mit AND oder OR verknüpfte Spalten.
Die Bitmap Indexes bestehen aus einer bitmap (oder bit vector) für jede verschiedene Spalte. Jede
Bitmap hat einen Bit für jeden Zeile in der Tabelle. Der Bit wird auf 1 gesetzt falls die Zeile einen
bestimmten Wert hat, auf 0 sonst.
Diese Indexes sind insbesondere brauchbar für Anfragen mit komplexen und unvorhersehbaren
zusammengesetzten Prädikaten in großen Tabellen. Das passiert, weil man sehr schnell AND- und
OR-Prädikate ausführen kann, auch wenn Millionen von Zeilen teilnehmen. Die entsprechenden
Operationen mit B-Tree Indexes sammeln und sortieren eine große Menge von Pointern.
Auch diese Art der Indexstruktur hat ihre Nachteile, denn durch ihre Struktur sind
Änderungsoperationen sehr aufwendig, da für sie Matrixmodifikationen nötig werden.
Das Beste bei richtig erstellten B-Tree Indexes ist es, dass sie den Tabellenzugriff eliminieren. Bei den
Bitmap Indexes müssen die Tabellen zugegriffen werden, außer die Anfrage nur COUNTs hat.
Deswegen kann manchmal in dem Fall dieser Indexes längere Ausführungszeiten auftreten.
44
Wir haben die bereits existierende B-Tree Indexes durch Bitmap Indexes ersetzt oder neue Join
Bitmap Indexes erstellt.
CREATE TABLESPACE idx_bm DATAFILE
'C:\oracle\product\10.2.0\oradata\tpch\idx_bm.dbf' SIZE 1M
AUTOEXTEND ON NEXT 500k;
CREATE BITMAP INDEX bi ON lineitem(l_shipdate) TABLESPACE idx_bm;
CREATE BITMAP INDEX bi2 ON part(p_size) TABLESPACE idx_bm;
CREATE BITMAP INDEX jbi_c_mktsegment ON orders(customer.c_mktsegment)
FROM orders, customer WHERE c_custkey = o_custkey TABLESPACE idx_bm;
CREATE BITMAP INDEX bi3 ON orders(o_orderdate) TABLESPACE idx_bm;
CREATE BITMAP INDEX jbm2 ON customer(orders.o_orderdate) FROM customer,
orders WHERE c_custkey = o_custkey TABLESPACE idx_bm;
CREATE BITMAP INDEX jbm3 ON lineitem(part.p_type) FROM lineitem, part
WHERE p_partkey = l_partkey TABLESPACE idx_bm;
CREATE BITMAP INDEX bm_l_returnflag ON lineitem(l_returnflag) TABLESPACE
idx_bm;
CREATE BITMAP INDEX bi_l_shipmode ON lineitem(l_shipmode) TABLESPACE
idx
bm;
Die
Ergebnisse
waren sehr zufriedend:
Bitmap Indexes
03:36,0
Zeit
02:52,8
02:09,6
01:26,4
00:43,2
00:00,0
Q1
Q2
Q3
Q4
Q6
Q8
Q12
Q13
Q14
Q16
Q19
Queries
nur PK
Bitmap
Ausführungszeiten der Anfragen mit Bitmap Indexes
Mit der Ausnahme von Q19 (0,8%), ist es in allen Fällen eine Verbesserung aufgetreten.
Durchschnittlich 34,5%. Das zeigt, dass die Bitmap Indexes eine sehr gute Alternative für die Bitmap
Indexes sein können.
2.2.5.6 Optimale Indexierung: Fazit
Indexes auf Spalten vom Typ DATE oder die indexierten Comment Spalten wurden in keinem Query
Plan benützt. PK wurde auch sehr oft im Query Plan nicht benützt. In Oracle sind die MehrspaltenIndexes besser als die Indexes für eine Spalte, und die FAT Indexes die besten.
Indexes sollen den Query Plan entsprechen. Zu viele Indices verursachen INSERT und UPDATE
Problemen. Die Index organisierte Tabellen (IOT) sind besser nur in den Fällen, wenn es keine Joins
gibt.
45
Der Indexierungsgrad hängt eng von der Art der Applikation ab. Ein hohes Indizierungsgrad steigt die
Geschwindigkeit der Anfragen und Berichten, verlangsamt aber die Update-Operationen. Deshalb ist
eine hohe Indexierung z. B. geeignet für Entscheidungssysteme und nicht geeignet für OLTPAnwendungen.
Die Indexierungsproblemen bei Oracle bestehen daraus, dass nicht immer die richtige Spaltennummer
in der richtigen Ordnung im Index sich befinden. Oft definiert man nicht genug Indexes oder erstellt
nur unnützliche.
Die Kosten für die Speicherung der Indexes kann zu gross sein. Mann sollte immer ein Gleichgewicht
zwischen der Zahl von Indexes und dem verfügbaren Speicherplatz.
Der Oracle Database Tuning Tool empfehlt meistens die Erstellung von Indexes. Man kann aber auch
bessere Optionen finden, wie z.B. materialisierte Views anlegen.
Indexdesign ist nicht einfach, wenn man einen Index für jede Anfrage erstellen muss (außer wenn
einen identischen Index existiert bereits). Man muss immer mehrere Faktoren berücksichtigen: die
SELECT Anfrage, Statistiken der Datenbank (Anzahl von Zeilen, Seiten, u.a.), bestehende Indexes,
usw.
3 Oracle Tuning Pack
Im Unterschied zur Oracle 10g XE bietet Oracle 10g EE die Möglichkeit mit dem Oracle Tuning Pack
zu arbeiten, welche die Laufzeit der Queires ohne großen Aufwand verbessern kann.
Die Tests gezeigten, dass nachdem die Primärschlüsseln erstellt wurden, hat die Laufzeit der Queries
sich verbessert. Die Graphische Darstellung zeigt, dass trotzt der Verbesserung ist die Laufzeit der
Queries: 3, 9, 10, 15, 18, 21 etwas länger als von der anderen Queries, daher werden bei der
Optimierung mit dem Oracle Tuning Pack nur diese 6 Queries betrachtet.
Oracle 10g allows the optimizer to run in tuning mode where it can gather additional
information and make recommendations about how specific statements can be tuned further. 24
SQL-Tuning werden vier Analysetypen ausgeführt:
• Statistische Analyse: Der Query Optimizer benötigt aktuelle Objektstatistiken, um gute
Ausführungspläne zu generieren. Bei diesem Analysetyp werden Objekte mit veralteten oder
fehlenden Statistiken identifiziert und geeignete Empfehlungen zur Lösung des Problems
gegeben.
24
[20] Automatic SQL Tuning in Oracle Database 10g
46
•
•
•
SQL-Profilerstellung: Dieses Feature ist neu in Oracle Database 10g und verkörpert einen
komplett revolutionierten SQL-Tuning-Ansatz. Bisher beinhaltet das SQL-Tuning die
manuelle Bearbeitung des Anwendungs-Codes mit Hilfe von Optimizer Hints. Durch die
SQL-Profilerstellung entfällt dieser manuelle Prozess. Mit der SQL-Profilerstellung wird das
Tuning automatisch und sofort durchgeführt.
Zugriffspfadanalyse: Indizes können die Performance einer SQL-Anweisung extrem
verbessern, weil nicht mehr so viele Full Table Scans notwendig sind. Die effektive
Indizierung ist daher eine gebräuchliche Tuning-Technik. Bei diesem Analysetyp werden neue
Indizes identifiziert und empfohlen, die die Abfrage-Performance beträchtlich steigern
können.
SQL-Strukturanalyse: Probleme mit der Struktur von SQL-Anweisungen können zu einer
schlechten Performance führen. Dabei könnte es sich um syntaktische, semantische oder um
Designprobleme der Anwendung handeln. Bei diesem Analysetyp werden relevante
Vorschläge zur Umstrukturierung der SQL-Anweisung gegeben, um die Performance zu
steigern.
Automatisches SQL-Tuning stellt eine umfassende SQL-Tuning-Lösung dar. Das automatische SQLTuning wird über zwei neue Advisor in Oracle Tuning Pack 10g bereitgestellt, SQL Tuning Advisor
und SQL Access Advisor, die in Enterprise Manager Database Control und Grid Control integriert
sind.
Automatisches SQL-Tuning ist über Enterprise Manager auf "Advisor Central" Seite oder über
PL/SQL durch das Nutzen des DBMS_SQLTUNE Packets zu erreichen. 25
Im folgen wird das Automatisches SQL-Tuning erst über PL/SQL eingesetzt.
3.1 Oracle Tuning Pack über PL/SQL
Um das SQL Tuning Advisor API zu erreichen, braucht der user das ADVISOR Privile:
SQL> CONN / AS SYSDBA
SQL> grant advisor to tpch
SQL> grant select_catalog_role to tpch;
SQL> GRANT EXECUTE ON DBMS_SQLTUNE TO tpch;
SQL> conn tpch/tpch;
Als erstes muss das neue Tuning Task erstellt werden:
-- Tuning task created for a manually specified statement. Q3
DECLARE
l_sql
VARCHAR2(1000);
l_sql_tune_task1 VARCHAR2(100);
BEGIN
L_sql:= 'select l_orderkey, sum(l_extendedprice * (1 - l_discount)) as revenue, o_orderdate, o_shippriority ' ||
'from customer, orders, lineitem ' ||
'where c_mktsegment = '||''''||'BUILDING'||''''||' and c_custkey = o_custkey and l_orderkey = o_orderkey and o_orderdate < date
'||''''||'1995-03-15'||''''||' and l_shipdate > date '||''''||'1995-03-15'||''''||' ' ||
'group by l_orderkey, o_orderdate, o_shippriority ' ||
'order by revenue desc, o_orderdate ' ;
l_sql_tune_task1 := DBMS_SQLTUNE.create_tuning_task (
sql_text => l_sql,
user_name => 'TPCH',
scope
=> DBMS_SQLTUNE.scope_comprehensive,
time_limit => 60,
task_name => 'emp_dept_tuning_taskQ3',
description => 'Tuning task for an EMP to DEPT join query.');
DBMS_OUTPUT.put_line('l_sql_tune_task1: ' || l_sql_tune_task1);
END;
/
25
[21] ORACLE TUNING PACK FOR DATABASE
47
Als nächstes muss das erstellte Tuning Task ausgeführt werden:
EXEC DBMS_SQLTUNE.execute_tuning_task(task_name => 'emp_dept_tuning_taskQ3');
Sobald das Tuning Task erfolgreich ausgeführt wird, können die Empfehlungen ausgeführt werden:
SET LONG 10000;
SET PAGESIZE 1000
SET LINESIZE 200
SELECT DBMS_SQLTUNE.report_tuning_task('emp_dept_tuning_taskQ3') AS recommendations FROM dual;
SET PAGESIZE 24
Braucht man das Tuning Task nicht mehr so kann es mit DROP_TUNING_TASK Funktion gelöscht werden:
BEGIN
DBMS_SQLTUNE.drop_tuning_task (task_name => 'emp_dept_tuning_taskQ3');
END;
/
Im folgen werden die Optimierungsvorschläge des Oracle Tuning Packs betrachtet, allerdings gab es
für Queries 10, 15 und 18 leider keine Verbesserungsvorschläge.
Von den restlichen Queires waren besonders die Vorschläge für Queries 3 und 9 interessant. Für
Query 3 werden diese Vorschläge etwas näher angeschaut.
Query 3
------------------------------------------------------------------------------EXPLAIN PLANS SECTION
------------------------------------------------------------------------------Ausführungsplan ohne SQL-Profil
48
Ausführungsplan mit SQL-Profil
Es ist deutlich zu sehen, dass falls man das empfohlene SQL-Profil akzeptiert verbessert sich die
Laufzeit von 00:54:70 auf 00:50:27.
Nachdem das empfohlene SQL-Profil akzeptieren wurde, konnte man die weiteren Empfehlungen des
Oracle Tuning Packs erhalten.
Führt man die restlichen Vorschläge des Oracle Tuning Packs aus, so Verbessert sich die Laufzeit auf
00:40:27.
3.2 Oracle Tuning Pack über Web Benutzeroberfläche
Oracle Tuning Pack bietet die Möglichkeit unter Web Benutzeroberfläche die Geschichte aller SQLAnfragen mit zusätzlichen Informationen zu bekommen. Unter Performance ÎTop Activity Î
Historical Î Period SQL ist eine Tabelle mit allen Anfragen zu sehen. Man kann eine bestimmte
Zeitspanne auswählen, für welche die Queries aufgelistet werden. Die ausgeführten Anfragen sind
nach Ausführungszeit/Kosten geordnet. Leider nicht auch chronologisch. Man kann eine bestimmte
Anfrage nicht suchen, sondern in der sehr langen Liste finden, wo auch die System-Anfragen gemischt
sind. Manchmal sind nicht alle Anfragen vorhanden. Das ist der Grund, warum uner Enterprise
Edition weniger Informationen über Ausführungspläne gefunden /gesucht gefunden wurden.
Bei Oracle gibt es auch einen Tuning Pack, mit dem man automatisch Anfragen optimieren kann. Um
zu sehen, ob es wirklich funktioniert, wurden Tests mit Query 5 durchgeführt. Am Anfang hat es 15
Minuten gedauert, um das Ergebnis zu sehen. Der Ausführungsplan war:
49
Bei Tuning Information war keine Information vorhanden:
Um Empfehlungen zu bekommen, musste man den Tuning Advisor starten.
Empfehlungen:
Oracle zeigt parallel auch die zwei Ausführungspläne: den empfohlene und den alten.
Die Empfehlung wurden durchgeführt:
50
Danach wurde die Query wieder ausgeführt und die Ausführungszeit hat sich deutlich verbessert: von
15:02,09 auf 02:48,68.
3.3 FAZIT
Es war sehr hilfreich mit Oracle Tuning Pack zu arbeiten. Kam der Optmierer mit den eigenen
Methoden nicht mehr weiter, so konnten nach den Empfehlungen des Oracle Tuning Packs
nachgeschaut werden. Unter PL/SQL waren sie leicht auszuführen aber immer noch etwas
komplizierter als unter Web Benutzeroberfläche, hier musste man selbst nichts implementieren, alle
Optimierungen wurden automatisch durchgeführt und man musste bei den Optimierungen nur
Zustimmen damit sie in Gang gesetzt werden konnten. Die Ergebnisse waren immer sehr
zufriedenstellend.
4 FAZIT der Optimierung
Die durchgeführten Tests mit den beiden DB Systemen haben gezeigt, dass obwohl es sehr leicht war
mit Oracle 10g XE zu arbeiten, bat dieses System nicht so viele Möglichkeiten für die Optimierung an.
Man hat gesehen, dass sehr viele Funktionen nicht aktiviert sind, Cluster führen zur Verschlechterung
und man hatte auch keine Möglichkeit gehabt mit Oracle Tuning Pack zu arbeiten. Ausführungszeiten
waren in allgemeinen viel schlechter bei Oracle XE als bei Oracle EE.
Im Unterschied zur Oracle XE war es etwas komplizierte mit Oracle EE zu arbeiten, man hatte
Schwierigkeiten bei der Installation, die Web Benutzeroberfläche hat oft nicht funktioniert und war
etwas unübersichtlicher als bei Oracle XE. Aber dieses System bat sehr viele Möglichkeiten für
Optimierung an, und vor allem man konnte hier immer mit Oracle Tunung Pack arbeiten, was zu sehr
guten Ergebnissen geführt hat.
Optimizers sind nicht perfekt
• Sie sehen nicht immer die beste Alternative
•
•
•
•
Insbesondere wenn service time > Anfrage time besteht diese Gefahr
Komplizierte Predikate (LIKE %)
Nicht nötige Sortierungen
Kosten falsch geschätzt
51
4.1 Oracle Tuning Tips
Die unten aufgelisteten Regeln sind einfach aber sehr hilfreich, wenn um die Performanz geht.
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
26
Do not index every column in the table - have only those indexes, which are required.
Distribute your data to parrallelise the IO operations among multiple disks especially for those
tables which have lots of IO's.
Try to avoid large data retrievals, since if the data being retrieved from a table is more than
10%-20% of the total data, Oracle will most likely do the FST.
Never do a calculation on an indexed column (e.g., WHERE salary*5 > :myvalue).
Whenever possible, use the UNION statement instead of OR conditions.
Avoid the use of NOT IN or HAVING in the WHERE clause. Instead, use the NOT EXISTS
clause.
Always specify numeric values in numeric form and character values in character form (e.g.,
WHERE emp_number = 565, WHERE emp_name = 'Jones').
Avoid specifying NULL in an indexed column.
Avoid the LIKE parameter if = will suffice. Using any Oracle function will invalidate the
index, causing a full-table scan.
Never mix data types in Oracle queries, as it will invalidate the index. If the column is
numeric, remember not to use quotes (e.g., salary = 50000). For char index columns, always
use single quotes (e.g., name = 'NAME').
Remember that Oracle's rule-based optimizer looks at the order of table names in the FROM
clause to determine the driving table. Always make sure that the last table specified in the
FROM clause is the table that will return the smallest number of rows. In other words, specify
multiple tables with the largest result set table specified first in the FROM clause.
Avoid using subqueries when a JOIN will do the job.
Use the Oracle "decode" function to minimize the number of times a table has to be selected.
To turn off an index you do not want to use (only with a cost-based optimizer), concatenate a
null string to the index column name (e.g., name||') or add zero to a numeric column name
(e.g., salary+0). With the rule-based optimizer, this allows you to manually choose the most
selective index to service your query.
If your query will return more than 20 percent of the rows in the table, use a full-table scan
rather than an index scan.
Always use table aliases when referencing columns. 26
[4] Oracle Tuning Tips
52
Literaturverzeichnis
[1]
Haas, F.: Oracle Tuning in der Praxis. Hanser, 2005.
[2]
Lahdenmäki, T., Leach, M.: Relational Database Index Design and the Optimizers. Wiley,
2005.
[3]
Mittra, S.: Database Performance Tuning and Optimization. Springer, 2003
[4]
Oracle Tuning Tips
http://blogs.ittoolbox.com/database/software/archives/oracle-tuning-tips-8151
[5]
Realisierung des TPC-H-Schemas auf einem Oracle-Datenbanksystem
ftp://ftp.informatik.uni-stuttgart.de/pub/library/medoc.ustuttgart_fi/STUD-1945/STUD-1945.pdf
[6]
TPC-H Schema erstellen
http://www.look-for-it.de/index.php?page=tpc-h-schema-erstellen
[7]
Datenbank Lizenzen
http://www.datenbank-lizenzen.com/datenbanklizenzen_smartm/html/f/10/oracle_datenbank_lizenzen_editionen.html
[8]
Datenbanksystem
http://www.it-academy.cc/article/1462/Datenbanksysteme.html
[9]
Oracle-Datenbankadministration für SAP
http://www.sap-press.de/download/dateien/1285/sappress_oracle_datenbankadmin.pdf
[10]
Oracle Konfigurationsoptionen
https://publib.boulder.ibm.com/tividd/td/tec/SC32-1233-00/de_DE/HTML/ecoimst96.htm
[11]
Oracle-Server Bestandteile
http://rowa.giso.de/oracle/latex/Oracle_Server_Bestandteile.html
[12]
http://www.adp-gmbh.ch/ora/concepts/cache.html
[13]
http://de.wikipedia.org/wiki/Sicht_%28Datenbank%29
[14]
Materialized Views
http://www.imn.htwk-leipzig.de/~ctheil1/DB2_vortrag/MaterializedViews_Dokument.pdf
[15]
Oracle: Einsatz von Partitioning
http://www.isr.de/news.nsf/0/B3A50BE438F6EF7BC1256FF00039BA5A?OpenDocument
[16]
Oracle: Einsatz von Partitioning (Teil 2)
http://www.isr.de/news.nsf/0/D7BA47F20C2F8DF3C1256FF00039BA61?OpenDocument
[17]
Oracle SQL im Überblick
http://www.inf.uni-konstanz.de/dbis/teaching/ws0102/informationssysteme/local/sql.pdf
[18]
Michael Ault: Oracle – Datenbanken Administration und Management. Mitp 2003
ISBN: 3-8266-1316-3
[19]
Datenbanksysteme
www.mpi-inf.mpg.de/departments/d5/teaching/ws99_00/dbs/uebungen/p4.ps
[20]
Automatic SQL Tuning in Oracle Database 10g
http://www.oracle-base.com/articles/10g/AutomaticSQLTuning10g.php
53
[21]
ORACLE TUNING PACK FOR DATABASE
http://www.oracle.com/lang/de/collateral/downloads/ORACLE_Tuning_Pack.pdf
[22]
Kevin Loney “Oracle Database 10g Die umfassende Referenz“
Oracle Press, ISBN: 3-446-22833-0
54
Herunterladen