Oracle 10G and Linux (Ubuntu)

Werbung
Seminar Database Tuning & Administration“
”
Ausarbeitung
Oracle Datenbank / Ubuntu
Sebastian Gath und Hannes Schwarz
Universität Konstanz
1
Einleitung
Heutige Datenbanken sind in der Lage, riesige Datenmengen zu speichern und
zu verwalten. Im Allgemeinen erhöhen sich jedoch die Antwortzeiten von Abfragen, Einträgen und Updates mit zunehmender Größe der Datenbank. Diese
Performanceeinbußen gilt es durch verschiedene Optimierungsmaßnahmen zu
minimieren. Da heutige Datenbanken einen immer größer werdenden Funktionsumfang bieten, gibt es zahlreiche Optimierungsmöglichkeiten, die nicht immer
das gewünschte Ergebnis liefern, da bei einer Anfrage sehr viele Faktoren eine
Rolle spielen.
Die vorliegende Seminararbeit befasst sich mit der Administration und der
Optimierung einer Oracle Datenbank auf einem Linux System. Das Ziel ist es,
eine praktische Darstellung der getätigten Arbeitschritte, die während des Seminars Database Tuning & Administration“ erledigt wurden, zu geben. Nach
”
der administrativen Vorbereitung, die die Installation des Betriebssystems, der
Datenbank und der Benchmark umfasst, wird auf die verschiedenen Optimierungen eingegangen. Dabei liegt der Schwerpunkt auf vier Anfragen des TPC-H
Benchmarks, an Hand derer verschiedene Techniken zur Optimierung gezeigt
und bewertet werden.
2
2.1
Administration
Vorbereitung
Als Ausgangssituation stand uns ein HP Compaq dc5750 Microtower mit einem
AMD Athlon 64 x2 Dual Core Prozessor 4600+ und 1 Gigabyte DDR2 RAM
zur Verfügung. Wir entschlossen uns bezüglich des Betriebssystems auf die freie
Linux-Distribution Ubuntu zurückzugreifen und installierten die 64-Bit Version
6.10 Edgy Eft“ mit Hilfe einer Installations-CD. Danach kam die Installati”
on der Oracle 10g Express-Version. Dazu nutzten wir das Debian Package, das
auf der Webseite von Oracle [Oracle] zur Verfügung stand. Mit dem Programm
dpkg werden die Dateien automatisch in die nötigen Verzeichnisse kopiert und es
müssen nur noch der Umgebungsvariablen hinzugefügt werden. Dies wird durch
die folgenden Befehle erreicht:
2
Sebastian Gath & Hannes Schwarz
# dkpg oracle-xe 10.2.0.1-1.0 i386.deb
# export
PATH=$PATH:/usr/lib/oracle/xe/app/oracle/product/10.2.0/server/bin
Als Benchmark wurde die Decision Support Benchmark TPC-H in der Version 2.6.0 vorgegeben. Die Benchmark nutzt für den Datenbanktest Anfragen und
Daten, die eine weitreichende Relevanz für die Industrie haben. Dabei handelt
es sich um ein Decision Support System, das große Datenmengen verarbeitet,
Anfragen mit einem hohen Grad an Komplexität ausführt und Antworten zu
kritischen Geschäftsfragen liefert.
Nach dem Download der nötigen Dateien von der TPC-H Webseite [TPC]
muss die Benchmark vor der Installation auf das System eingestellt werden.
Hierzu wird ein Makefile mitgeliefert, in dem drei Parameter angepasst werden
müssen, welche wir wie folgt wählten:
CC = gcc
DATABASE = DB2
MACHINE = LINUX
Da der Datenbanktyp Oracle nicht zur Verfügung stand, wählten wir DB2.
Nach dem Speichern der Datei musste der C-Compiler gcc und dessen C-Bibliotheken
installiert werden. Dazu dienten diese Befehle:
# apt-get install gcc
# apt-get install gcc-lib
Anschließend konnten die TPC-H Quelldateien mit Hilfe des Makefiles kompiliert werden und die Programme dbgen und qgen wurden erstellt. Als nächstes
war die Aufgabe, die Daten zu erzeugen und diese dann in der Datenbank zu speichern. Dazu muss das Tool dbgen genutzt und ein Skalierungsfaktor angegeben
werden, mit dessen Hilfe die Datenmenge angeben wird. Ein Skalierungsfaktor
von 1.0 erzeugt Daten von etwa einem Gigabyte. Als Grundlage für unsere Tests
erzeugten wir mit folgendem Befehl Daten von einem Gigabyte, da die Express
Version nur maximal 5 Gigabyte unterstützt.
# dbgen -s 1.0
Dbgen erstellt durch diesen Befehl zehn Dateien, acht tbl Dateien, die die
Daten beinhalten, eine dss.ddl Datei, mit den Spezifikation der Tabellen und
eine dss.ri Datei, in der die Schlüssel der Tabellen definiert sind. Da die Syntax
nicht ganz Oraclekonform war und um später nicht immer alle Tabellen neu
einspielen zu müssen, erstellten wir passend zu den acht Tabellen einzelne SQLSkripte mit dem Namen ctTABELLE.sql, die die Befehle aus der dss.ddl und
dss.ri vereinten. Folgend als Beispiel für die Tabelle part:
Um diese Tabellen zu erstellen, nutzten wir die Shell und das kommandozeilenbasierte Werkzeug von Oracle sqlplus mit folgendem Befehl:
# for i in ct*.sql do sqlplus benutzername/passwort @$i done
Database Tuning & Administration: Oracle/Ubuntu“
”
3
drop table part;
CREATE TABLE PART ( P PARTKEY NUMBER(7,0) NOT NULL,
P NAME VARCHAR2(55) NOT NULL,
P MFGR varCHAR2(25) NOT NULL,
P BRAND varCHAR2(10) NOT NULL,
P TYPE VARCHAR2(25) NOT NULL,
P SIZE NUMBER (3,0) NOT NULL,
P CONTAINER varCHAR2(10) NOT NULL,
P RETAILPRICE NUMBER(15,2) NOT NULL,
P COMMENT VARCHAR2(23) NOT NULL,
constraint part pk PRIMARY KEY (p partkey));
Abbildung 1. Beispiel für das SQL-Skript zum Erstellen der Tabelle Part
Dadurch wurden alle Tabellendefinitionen in der Datenbank erstellt.
Bevor nun die Daten in die Tabellen geladen werden konnten, musste noch
das Datumsformat der Datenbank an die Daten angepasst werden. Dies konnte
dauerhaft in sqlplus mit dem unten stehenden Befehl erreicht werden.
> alter system set nls date format=‘YYYY-MM-DD
HH24:MI:SS‘scope=spfile;
Anschließend konnten die Daten in die Datenbank b̈ertragen werden. Dies
wurde durch den Bulk Loader sglldr von Oracle erreicht. Dazu nutzen wir dieses
Skript, welches mit Hilfe des Bulk Loaders aufgerufen und ausgefhrt wurde.
LOAD DATA
INFILE ’part.tbl’
INSERT INTO TABLE part
FIELDS TERMINATED BY ‘|‘
(p partkey, p name, p mfgr, p brand, p type, p size, p container,
p retailprice, p comment)
Abbildung 2. Beispiel für das SQL-Skript zum Füllen der Tabelle Part
Als Ergebnis stand das in Abbildung (3) ersichtliche Schema in der Datenbank zur Verfügung. Die fett gedruckten Attribute nutzen wir als Primärschlüssel.
Wir nahmen von der Idee abstand, Tabellen ohne Primärschlüssel anzulegen, da
dies in der Praxis nicht üblich ist.
Desweiteren sind die Verbindungen der Tabellen untereinander durch die
Pfeile dargestellt. Diese Attribute bieten sich als Fremdschlüssel an, die wir jedoch nicht genutzt haben. Letztendlich bildet dieses Schema die Grundlage des
TPC-H Benchmarks, die wir zur Leistunsmessung herangezogen haben.
4
Sebastian Gath & Hannes Schwarz
PART
PARTSUPP
LINEITEM
ORDERS
200.000 Einträge
P_PARTKEY
P_NAME
P_MFGR
P_BRAND
P_TYPE
P_SIZE
P_CONTAINER
P_RETAILPRICE
P_COMMENT
800.000 Einträge
PS_PARTKEY
PS_SUPPKEY
PS_AVAILQTY
PS_SUPPLYCOST
PS_COMMENT
6.000.000 Einträge
L_ORDERKEY
L_PARTKEY
L_SUPPKEY
L_LINENUMBER
L_QUANTITY
L_EXTENDPRICE
L_DISCOUNT
L_TAX
L_RETURNFLAG
L_LINESTATUS
L_SHIPDATE
L_COMMITDATE
L_RECIEPTDATE
L_SHIPINSTRUCT
L_SHIPMODE
L_COMMENT
1.500.000 Einträge
O_ORDERKEY
O_CUSTKEY
O_ORDERSTATUS
O_TOTALPRICE
O_ORDERDATE
O_ORDERPRIORITY
O_CLERK
O_SHIPPRIORITY
O_COMMENT
SUPPLIER
10.000 Einträge
S_SUPPKEY
S_NAME
S_ADDRESS
S_NATIONKEY
S_PHONE
S_ACCTBAL
S_COMMENT
CUSTOMER
150.000 Einträge
C_CUSTKEY
C_NAME
C_ADDRESS
C_NATIONKEY
C_PHONE
C_ACCTBAL
C_MKTSEGMENT
C_COMMENT
NATION
25 Einträge
N_NATIONKEY
N_NAME
N_REGIONKEY
N_COMMENT
REGION
5 Einträge
R_REGIONKEY
R_NAME
R_COMMENT
Abbildung 3. TPC-H Schema mit einem Scaling-Factor von 1.0
2.2
Leistungsmessungen
Zur Zeitmessung wurde ein Shellskript genutzt, das die Anfragen in zwei Varianten ausführte. In der ersten Variante wurde jede Anfrage des Benchmarks
mehrfach hintereinander ausgeführt. In der zweiten Variante wurden alle Anfragen des Benchmarks einmal ausgeführt und dies mehrfach hintereinander. Das
Ergebnis wurde in zwei Dateien, eine für jede Variante, gespeichert, um diese
später weiterzuverarbeiten. Im folgendem Beispiel ist das Shellskript zur Leistungsmessung nach Variante zwei zu sehen.
for x in ‘seq 1 10‘
do
echo XXXXXXX $x XXXXXXXXX >> Var2.txt
for i in *.sql
do
echo -n $i: >> Var2.txt
sqlplus Benutzername/Passwort @$i | grep Elapsed >> Var2.txt
echo
done
done
Database Tuning & Administration: Oracle/Ubuntu“
”
5
Wir erhofften uns durch diese zwei Varianten, den Caching-Effekt auszuschalten und gingen davon aus, dass die zweite Variante eine längere Laufzeit
aufweisen würde. Wie später im Abschnitt (4) Datenbankoptimierungen zu sehen sein wird, war dies nicht der Fall. Eine weitere Möglichkeit der Analyse der
Anfragen waren die Ausführungspläne, die von Oralce zur Verfügung gestellt
werden. Diese können in sqlplus mit dem Befehl SET AUTOTRACE ON vor der
Abfrage verlangt werden und werden nach der Ausführung der Anfrage angezeigt.
2.3
Erste Zeitmessung
Abbildung 4. Eine erste Zeitmessung der Anfragen ohne Optimierung
Eine erste Zeitmessung aller Anfragen des Benchmarks ist in Abbildung (4)
zu sehen. Die Anfragen wurden vorab nach vorkommenden SQL Statements
gruppiert und entsprechend ihrer Zugehörigkeit eingefärbt, um einen Überblick
über die Art und Laufzeit der Anfrage zu geben. So stehen z.B. die roten Punkte
für eine select Anfrage, in dessen from Teil ein weiteres select ausgeführt wird.
Anhand der X-Achse ist die Zeit logarithmisch abgetragen, da die Zeitunterschie-
6
Sebastian Gath & Hannes Schwarz
de zwischen den Abfragen sehr groß ist. Die langsamsten Anfragen befinden sich
daher auf der rechten Seite.
Unter Zuhilfenahme dieser Zeitmessung haben wir uns für vier Anfragen entschieden, die zur Optimierung herangezogen wurden und dessen Optimierungsmaßnahmen im Folgenden beschrieben werden. Die Entscheidung fiel auf diese
Anfragen, da hier unserer Meinung Veränderungen schneller sichtbar werden und
sie eine heterogene Mischung der Anfragen darstellen.
3
Anfragenoptimierungen
Zu Beginn unserer Optimierungsmaßnahmen beschäftigten wir uns mit den zuvor ausgewählten Anfragen 2, 3, 13 und 22. Im Folgenden werden auf die einzelnen Ideen zur Optimierung und dessen Auswirkungen auf die jeweiligen Anfragen
eingegangen.
3.1
Anfrage 13
select c count, count(*) as custdist
from (
select c custkey, count(o orderkey) c count
from customer left outer join orders on
c custkey = o custkey
and o comment not like ’%special%requests%’
group by c custkey
) c orders
group c count
order by custdist desc, c count desc;
Abbildung 5. Anfrage13
In Anfrage 13 (Abbildung (5)) handelt es sich bei den zeitintensiven Berechnungen um einen left outer join und eine Substringsuche mit mehreren
Platzhaltern (not like). Der von Oracle zur Verfügung gestellte Ausführungsplan ist in Abbildung (6) zu sehen. Dort bestätigt sich die Annahme, dass es
sich bei diesen Stellen um die Flaschenhälse der Anfrage handelt. Wie hier sehr
gut zu sehen ist, benötigt die Ausführung des Joins und die Substringsuche ca.
50% der Gesamtlaufzeit und sind daher Ziel unserer Optimierungen.
Idee 1 - Vermeiden von Substringsuche auf Attribut ’o comment’
Um die Substringsuche zu vermeiden, legten wir eine Kodierung für normale
Database Tuning & Administration: Oracle/Ubuntu“
”
7
Abbildung 6. Ausführungsplan für Anfrage 13
Aufträge und Special Requests fest. Das Attribut o nonspecial wurde zu diesem
Zweck angelegt. Alle Anfragen, die einen Special Request darstellen, werden somit mit einer 1 im Attribut o nonspecial markiert. Dadurch wird die Suche auf
dem Textfeld vermieden und stattdessen durch eine einfache Abfrage des Attributs ersetzt. Die Anfrage ändert sich daraufhin nur geringfügig, wie in Abbildung
(7) zu sehen ist. Die Laufzeit der Anfrage sank daraufhin von 3.05 Sekunden
select c count, count(*) as custdist
from (
select c custkey, count(o orderkey) c count
from customer left outer join orders on
c custkey = o custkey
and o nonspecial=1
group by c custkey
) c orders
group c count
order by custdist desc, c count desc;
Abbildung 7. Anfrage 13 optimiert - Tuningidee I
auf 2.48 Sekunden im Schnitt, wobei es sich um eine Verbesserung von 20%
handelt. Durch das Einfügen und Füllen des Attributs o nonspecial steigt der
Speicherverbrauch und die Anwendungsprogramme bzw. Anfragen, die die Optimierung nutzen sollen, müssen angepasst werden. Weitere Optimierungsschritte,
die durchgeführt werden könnten, allerdings in unserer Oracle Datenbankversion
nicht freigeschaltet sind, wären zum einen das Anlegen eines Index auf das Attribut o nonspecial. Allerdings würden wir dadurch eher eine Verschlechterung
erwarten, da wir im Laufe dieser Arbeit feststellen konnten, dass bei der Benutzung von Indizes weniger oft mehr ist. Zum anderen könnte die Tabelle Orders
8
Sebastian Gath & Hannes Schwarz
nach dem Attribut o nonspecial partitioniert werden, was die Anfrage sicherlich beschleunigen würde, dies jedoch wahrscheinlich einen negativen Effekt auf
andere Anfragen hätte, der in keinem Verhältnis steht.
Idee 2 - Optimieren des left outer join orders on c custkey = o custkey
Um den left outer join zu optimieren, wurden die Tabellen Orders und Customer mit dem Primärschlüssel custkey geclustert gespeichert. Dazu erstellten
wir die neuen Tabellen Ordersc und Cumstomerc, um zunächst keine negativen
Effekte auf andere Anfragen hervorzurufen, mit denen wohl gerechnet werden
muss. Durch ein Cluster wird unter anderem der Speicher effizienter genutzt,
allerdings ist das Einfügen und Verändern der geclusterten Tabellen langsamer.
Nach Anpassung der Anfrage traten drastische Performanzeinbußen auf und wir
verfolgten die Idee nicht weiter.
3.2
Anfrage 22
select cntrycode, count(*) numcust, sum(c acctbal) totacctbal
from (select substr(c phone, 1, 2) cntrycode, c acctbal
from customer
where substr(c phone, 1, 2)
in (’13’, ’31’, ’23’, ’29’, ’30’, ’18’, ’17’)
and c acctbal > (select avg(c acctbal)
from customer
where c acctbal > 0.00
and substr(c phone, 1, 2) in
(’13’, ’31’, ’23’, ’29’, ’30’, ’18’, ’17’))
and not exists (select *
from orders
where o custkey = c custkey)) custsale
group by cntrycode
order by cntrycode;
Abbildung 8. Anfrage22
Anfrage 22 (Abbildung (8)) stellt eine typische Anfrage aus der Industrie dar.
Hierbei werden Kunden aus bestimmten Gebieten gesucht, indem diese durch
ihre Telefonvorwahl identifiziert werden. Dazu wird in der Anfrage und der Unteranfrage eine Substringsuche auf den ersten beiden Stellen der Telefonnummer
ausgeführt. Wie auch in Abbildung (9) zu sehen ist, handelt es sich bei der
Substringsuche ähnlich zu Anfrage 13 um den zeitintensivsten Teil der Anfrage.
Database Tuning & Administration: Oracle/Ubuntu“
”
9
Abbildung 9. Ausführungsplan für Anfrage 22
Idee 1 - Vermeiden von Substringsuche auf Attribut o comment
Die erste Optimierung orientiert sich an den Ideen der Anfrage 13. Da es sich bei
der Substringsuche um die Vorwahl, genauer gesagt die Ortskennzahl, handelt,
lag die Idee nahe, die Telefonnummer aufzuteilen. Dazu wurde das neue Attribut area code in die Tabelle eingefügt. Anschließend wurden die ersten beiden
Stellen der Telefonnummer (c phone) ausgeschnitten und in dem neuen Attribut
gespeichert. Der Vorteil liegt auf der Hand. Nun muss keine teure Substringsuche mehr ausgeführt werden, sondern es reicht das Attribut area code auszulesen
und es kommt, wie zuvor in Anfrage 13, zu einem Zahlenvergleich. Durch diese Optimierung wurde eine Laufzeitverkürzung von ca. 25% (Vorher: 1,98 sek;
Nachher: 1,51 sek) ohne Änderung des Speicherverbrauchs erreicht. Nachteil ist
jedoch, dass jede Anwendung, die die Tabelle verwendet, angepasst werden muss,
da diese sonst die Telefonnummer ohne Vorwahl anzeigen würde.
Idee 2 - Optimierung des Operators not exists
Eine weitere Optimierung versuchten wir durch Umschreiben der Anfrage zu
erreichen. Dies ist in Abbildung (10) zu erkennen. Idee war es, den Operator not
exists durch den Mengenoperator minus zu ersetzen. Die Laufzeit der Anfrage
erhöhte sich von den ursprünglich 1,98 Sekunden auf 3,61 Sekunden, was fast
eine Verdoppelung der Laufzeit bedeutet.
3.3
Anfrage 2
Zunächst einmal fällt bei der in Abblidung (11) gezeigten Anfrage auf, dass der
Join über die Tabellen partsupp, supplier, nation und region in der äußeren,
10
Sebastian Gath & Hannes Schwarz
select...
from customerAC,
(select c custkey from customerAC
minus select o custkey from orders ) ominu
where (c areacode = 13 or c areacode = 31 ...)
and c acctbal > (select ...
where c acctbal > 0.00
and (c areacode = 13 or c areacode = 31 ...))
group by cntrycode
...
Abbildung 10. Anfrage 22 optimiert - Tuningidee 2 (Anfrage gekürzt)
select ...
from part, supplier, partsupp, nation, region
where p partkey = ps partkey and s suppkey = ps suppkey
and p size = 15 and p type like ’%BRASS’
and s nationkey = n nationkey and n regionkey = r regionkey
and r name = ’EUROPE’and ps supplycost = (
select min(ps supplycost)
from partsupp, supplier, nation, region
where p partkey = ps partkey
and s suppkey = ps suppkey
and s nationkey = n nationkey
and n regionkey = r regionkey
and r name = ’EUROPE’ )
order by s acctbal desc, n name, s name, p partkey;
Abbildung 11. Anfrage2 - gekürzt
wie auch in der Subanfrage, vorkommt. Jedoch findet bei der äußeren Anfrage noch eine Selektion auf p size = 15 and p type like ’%BRASS’ statt. Wie
dem Ausführungsplan (Abbildung (12)) zu entnehmen ist, macht die Berechnung dieser Selektion ca. die Hälfte der gesamten Anfrageverarbeitungszeit aus.
Die verbleibende Anfrageverarbeitungszeit wird von dem Nested Loops Join der
Tabellen partsupp und part ausgeschöpft. Somit sind hier Tuningmaßnahmen
anzusetzen.
Idee 1 - Selektion auf p size = 15 and p type like ’%BRASS’ beschleunigen
Durch die Definition eines Bitmapindexes auf das Attribut p size könnte eine
Beschleunigung der Anfragebearbeitung erreicht werden, da so der Full Table
Database Tuning & Administration: Oracle/Ubuntu“
”
11
Abbildung 12. Ausführungsplan für Anfrage 2
Scan entfällt. Ein Bitmapindex ist notwendig, da das Attribut p size nicht eindeutig ist. Dies ist in der Expressversion nicht möglich, aber es ist zu vermuten,
dass die Beschleunigung eher gering ausfallen würde, da die Selektivität des Attributes p type gering ist.
Eine weitere Möglichkeit wäre die Definition eines Textindexes auf dem Attribut p type. Textindexe sind jedoch sehr speicherintensiv und führen nicht
zwangsläufig zu Performanceverbesserungen. Da hier eine führende Wildcard
in like ’%BRASS’ verwendet wird, ist ein Full Table Scan notwendig und so
die einfache Suche in dem Textfeld effizienter, da der von Oracle eingesetzte
Textindizes solche Anfragen nicht effizient unterstützt.
Idee 2 - Tabellen nation/region geclustered speichern
Um das Joinen der Tabellen nation/region zu beschleunigen, würde es sich
anbieten, beide Tabellen geclustert zu speichern. Das Clustern hätte zur Folge,
dass Tupel aus beiden Tabellen, die den gleichen Schlüsselwert haben, zusammenhängend auf der Festplatte gespeichert werden und so das Lesen effizienter
möglich ist. Da dieser Join in vielen Anfragen des TPC-Benchmarks vorkommt,
würde diese Tuningmaßnahme auch andere Anfragen beschleunigen. Allerdings
enthalten die beiden Tabellen so wenige Tupel, dass kein messbarer Effekt durch
die Maßnahme erzielt werden kann.
Idee 3 - Unteranfrage durch Materialized View und Partitionierung
beschleunigen
12
Sebastian Gath & Hannes Schwarz
Eine andere Optimierungsmöglichkeit wäre das Anlegen einer Materialized
View mit r name, p partkey und min(ps supplycost) as min supplycost als Attribute. Diese sollte nach dem Attribut r name partitioniert werden, da so nicht nur
eine Beschleunigung für Selektion auf r name = ’EUROPE’, sondern auch auf
alle anderen Ausprägungen des Attributs p name erreicht werden kann. Je Partition müsste noch ein Index auf p partkey definiert werden und die min supplycost
könnten aus den Materialized View Statistiken ermittelt werden.
Da diese Definition der Materialized View so in der Expressversion nicht möglich
ist, haben wir eine Tabelle mit einer Struktur erzeugt, die der Partition r name =
’EUROPE’ entspricht. Das Erzeugen einer Materialized View geht immer auch
mit einem steigenden Speicherverbrauch einher und führt zu erhöhtem Overhead bei Änderungen oder Einfügungen neuer Tupel in eine der Basistabellen,
da die Materialized View aktualisiert werden muss. Dies kann in Oracle durch
Setzen einer Refresh-Clause auf ON COMMIT automatisiert werden. Es werden so Änderungen der Basistabelle nach dem Commit auch in der Materialized
View übernommen.
Das Einbinden der Tabelle in die Anfrage führt zu einer Verkürzung der Laufzeit
von ca. 20% (Vorher: 0.39 sek; Nachher: 0.31 sek). Der Einsatz einer Materialized View, wie oben beschrieben, würde zu einer ähnlichen Laufzeit führen, da
der Overhead kaum größer ist als der bei einem Tabellenzugriff.
3.4
Anfrage 3
select l orderkey, sum(l extendedprice * (1 - l discount)) 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;
Abbildung 13. Anfrage 3- gekürzt
In Anfrage 3 (Abbildung (13)) sind zwei Selektion über Datumsbereiche enthalten, deren Perfomance oft problematisch ist. Der von Oracle generierte Anfrageplan, zu sehen in Abbildung (14), zeigt sehr deutlich, dass die Auswertung
der Selektion o orderdate < date ’1995-03-15’ rund 90% der Laufzeit ausmacht.
Die verbleibenden zehn Prozent werden genutzt, um die Selektion c mktsegment
= ’BUILDING’ zu berechnen. Bei beiden Selektionen ist jeweils ein Full Table
Database Tuning & Administration: Oracle/Ubuntu“
”
13
Access notwending. Hier ist durch die Wahl geeigneter Tuningmaßnahmen eine
effizientere Verarbeitung sicherzustellen.
Abbildung 14. Ausführungsplan für Anfrage 3
Idee 1 - Selektion o orderdate < date ’1995-03-15’ durch Materialized
View beschleunigen
Ohne eine Tuningmaßnahme erzielt die Anfrage 2 eine Laufzeit von 0.95 Sekunden. Da im Durchschnitt 623 o orderkeys je o orderdate vorhanden sind,
wäre die Definition einer Materialized View mit den Attributen o orderdate,
o orderkey, o custkey und o shippriority zweckmäßig. Diese Attribute werden
für die weitere Verarbeitung der Anfrage benötigt. Die Materialized View könnte nach o orderdate je Jahr/Monat partitioniert werden, d.h. es werden alle
o orderdate die dem gleichen Jahr/Monat angehören in der gleichen Partition
gespeichert. Die Partitionen könnten wiederum mit einem Bitmapindex auf dem
Attribut o orderdate versehen werden. Ein Bitmapindex ist zu wählen, da das
Attribut o orderdate nicht eindeutig ist.
Da weder das Definieren eines Indexes auf Materialized Views, noch das Partitionieren in der Expressversion erlaubt ist, haben wir eine Tabelle erstellt, die
jedoch unpartitioniert, alle Daten die die Selektionsbedingung erfüllen, fasst. So
kann eine Reduzierung der Laufzeit um ca. 73 Prozent (0.26 Sekunden) erreicht
werden. Dieser Wert kann durch den Einsatz einer wie oben gezeigten Materialized View nahezu erreicht werden, da der Overhead durch die Partitionierung
sehr gering ist.
Idee 2 - Selektion c mktsegment = ’BUILDING’ beschleunigen
Bei der Auswertung der Selektion c mktsegment = ’BUILDING’ führt Oracle
14
Sebastian Gath & Hannes Schwarz
eine Full Table Access durch, der über 150.000 Datensätze in der Tabelle customer geht. Von diesen 150.000 Datensätzen erfüllen 30.142 (ca. 20 Prozent) die
Selektionsbedingung, d.h. die Selektivität des Attributs c mktsegment ist nicht
sehr hoch. Die Definition eines Textindexes auf diesem Attribut wäre somit wenig zweckmäßig. Die Nachteile der geringen Selektivität kann die Definition eines Bitmapindexes nicht verbessern, jedoch kann hierdurch erreicht werden, dass
Datensätze mit gleicher Ausprägung im Attribut c mktsegment zusammenliegen
auf der Festplatte gespeichert werden und so effizient gelesen werden können.
Dies konnten wir leider aufgrund fehlender Funktionalität nicht testen.
3.5
Ergebnisse im Überblick
3.0
Abbildung (15) zeigt noch einmal die Tuningergebnisse für die Anfragen 2, 3,
13 und 22 im Überblick. Vorallem bei Anfrage 3 konnte durch den Einsatz einer
Materialized View die Laufzeit erheblich verbessert werden.
1.5
0.0
0.5
1.0
Laufzeit (sek)
2.0
2.5
Nicht optimiert
Optimiert
2
3
13
22
Queryname
Abbildung 15. Tuningergebnisse für Anfragen 2, 3, 13 und 22 im berblick
4
4.1
Datenbankoptimierungen
Allgemeine Anmerkungen
Neben dem Definieren von Indexstrukturen, Einsetzten von Materialized Views
oder dem Clustern von Tabellen, kann versucht werden über Hints Einfluss auf
den vom Optimierer erzeugten Ausführungsplan zu nehmen. So kann z.B. dem
Database Tuning & Administration: Oracle/Ubuntu“
”
15
Optimierer die Verwendung eines Indexes oder eines bestimmtes Joinalgorithmuses nahegelegt werden, ohne das sichergestellt ist, dass dieser auch so verfährt.
Die Möglichkeiten von Hints sind bei den beschriebenen Optimierungen unberücksichtigt geblieben, da wir uns auf andere Tuningmaßnahmen konzentriert
haben.
Hints, genauso wie die in Kaptiel (3) gezeigten Methoden, beeinflussen zunächst
einmal nur die Laufzeit der gezeigten Anfragen, können jedoch durch Anpassung
anderer Anfragen auch deren Laufzeiten beeinflussen. Oracle bietet darüberhinaus die Möglichkeit, Datenbankparameter je Tablespace oder auch für die gesamte Datenbank zu ändern. Da wir alle Tabellen in keinem speziellen Tablespace
angelegt haben, beziehen sich die im Folgenden beschriebenen Änderungen auf
die gesamte Datenbank. Die geänderten Parameter können auch für jeden Tablespace individuell angepasst werden.
4.2
Ausgangssituation & Möglichkeiten
Das den Messungen zugrundeliegen System besitzt 1 GB RAM, von dem jedoch
nur ca. 944 MB zur Verfügung stehen. Oracle reserviert sich standardmäßig 41
des gesamten Arbeitsspeichers, im konkreten Fall waren dies 236 MB. Dieser
reservierte Bereich wird auch SGA - System Global Area genannt und lässt sich
über die Systemvariable sga max size setzten. So setzt z.B. der Befehl Alter system set sga max size = 512M die SGA auf 512 MB. Die SGA lässt sich grob
in den Buffer Cache, also der klassische Datenbankcache für Datenbanksegmente wie Tabellen oder Indizes und in die Shared Pools einteilen. Diese speichern
Ausführungspläne oder auch Data Dictionary Daten.
Durch das Setzten der sga max size übernimmt Oracle die genau Verteilung des
Arbeitsspeichers auf die einzelnen Komponenten. Auf der anderen Seite ist es
natürlich auch möglich, die Komponenten einzeln zu setzten. Zusätzlich gibt es
noch eine Reihe weiterer Cachegrößen, die gesetzt werden können, wie z.B. Caches die genutzt werden, wenn Oracle aus Anwendungen heraus angefragt wird.
Oracle bietet mit der Systemtabelle v$shared pool advice eine Vorhersage, wie
sich Veränderungen der Cachegröße auf die Laufzeit von Anfragen auswirken.
Im Folgenden wird dieser Aspekt näher erläutert.
Als Startkonfiguration sind alle Tabellen mit Primärschlüsselen und Index auf
dem Primärschlüsselattribut angelegt worden, da das Erstellen einer Tabelle ohne Primärschlüssel und passendem Index den Einsatz eines Datenbanksystems
überflüssig macht. In dieser Konfiguration könnten die Daten auch in einer einfachen Datei gespeichert und über Ubuntu-Boardmittel verarbeitet werden. Auch
wurde die Möglichkeit, Tabellen dauerhaft im Cache zu halten, zunächst außer
Acht gelassen. Der Befehl alter table tab storage (buffer pool keep) erzwingt das
Halten der Tabelle tab in dem Bufferpool keep, d.h. die Tabelle tab steht im
Hauptspeicher zur Verfügung und muss nicht von der Festplatte gelesen werden.
16
4.3
Sebastian Gath & Hannes Schwarz
Ergebnisse
Das in Kapitel (2.2) eingeführte Skript ermittelt die durchschnittliche Laufzeit
einer Anfrage bei einer 1000fachen Ausführung. Eine solche Art zu messen ist
jedoch sehr unrealistisch, da mit sehr hoher Wahrscheinlichkeit im realen Betrieb exakt die gleiche Anfrage nicht mehrfach hintereinander ausgeführt wird.
Jedoch macht es das Auswerten der Zeiten sehr viel einfacher.
Ein etwas realistischeres Anfrageverhalten kann durch einmaliges Ausführen jeder Anfrage nacheinander und vielfache Wiederholung dieses Schrittes erreicht
werden, wobei die Auswertung der Zeiten noch einfach zu handhaben ist. Durch
zufällige Wiederholung der Anfragen wären die Ergebnisse wahrscheinlich am
Realistischsten, jedoch gestaltet sich hier die Auswertung weit aus schwieriger.
Abbildung (16) zeigt die Messergebnisse der beiden beschriebenen Varianten, auf
allen Anfragen angewendet, im ÜberblickS. Anfragen mit einer Laufzeit unter
0.01 Sekunden wurden aus Gründen der Übersichtlichkeit nicht visualisiert.
Abbildung 16. Laufzeiten unter verschiedenen Einstellungen
Die hellroten und hellblauen Balken zeigen jeweils die Anfragezeiten aufgrund von Messung, bei denen die gleiche Anfragen 100 mal hintereinander ausgeführt wurde. Blaue Balken stehen für einen sga max size von 236 MB, rote
Balken hingegen für 512 MB. Die dunkelroten und dunkelblauen Balken stehen
für Anfragezeiten denen eine einmalige Ausführung jeder Anfrage und 100 fache
Database Tuning & Administration: Oracle/Ubuntu“
”
17
Wiederholung dieses Schrittes zu Grunde liegt.
Es lässt sich anmerken, dass die hellblaue 236 MB sga max size Variante tendenziell am Langsamsten ist. Vermutlich ist Oracle standardmäßig auf den Mehrbenutzerbetrieb optimiert und erwartet nicht, dass die gleiche Anfrage vielfach
hintereinander ausgeführt wird, wie auch der teils deutliche kürzere dunkelblaue
Balken zeigt. Anfrage 15 stellt hier eine Ausnahme dar. Ursächlich hierfür ist
das temporäre Anlegen einer View in dieser Anfrage, welche bei mehrfachem
Ausführen der Anfrage sehr wahrscheinlich im Cache gehalten wird und so zu
einer Performancesteigerung führt.
Sehr auffällig ist, dass das hinzufgen von mehr Cache nicht zwangsläufig auch
zu einer Performancesteigerung führen muss. Anfragen, die den vorhandenen
Cache nicht voll ausnutzen, können nicht durch Bereitstellung weiterem Caches
beschleunigt werden, da sie diesen nicht nutzen. Tuningeffekte durch gesteigerten
Cache hängt also immer von der Speicherauslastung vor der Tuningmaßnahme
ab.
Der gelbe Balken zeigt den Effekt des Haltens der Tabelle orders im Cache. Anfragen, die diese Tabelle nutzen, erfahren so eine Performancesteigerung (z.B.
Anfrage 22). Allerdings wird so der für Anfragen zur Verfügung stehende Hauptspeicher reduziert und kann gegebenenfalls dazu führen, dass Tabellen nicht mehr
gecached werden können und so aufwendige Leseoperationen von der Festplatte
notwendig sind, was von Performanceeinbußen zur Folge hat.
5
Fazit
Abschließend lässt sich festhalten, dass Operationen wie das Definieren von Partitionierungen, Bitmapindexe, Indexe auf Materialized Views in der Expressversion nicht möglich sind und so die Möglichkeiten doch erheblich einschränken.
Hinzu kommt eine Begrenzung der maximalen Datenbankgröße auf 5 GB. Somit
war das Erstellen einer 10 GB Instanz der TPC-Daten leider nicht möglich. Auch
standen der SQL Tuning Advisor und Access Advisor, beides Tools die automatisch Tuningvorschläge generieren, nicht zur Verfügung und es ist zu vermuten,
dass noch eine Reihe weiterer Features in der Expressversion nicht unterstützt
werden.
Festzuhalten ist, dass der von Oracle eingesetzte Optimierter bereits ohne Eingriffe sehr gut arbeitet. Der allgemeine Einsatz von Indexen führt nicht zwangsläufig
zu einer Performancesteigerung. Dennoch sind Performancesteigerungen mit akzeptablen Kosten und Auswirkungen auf andere Anfragen möglich, welche jedoch
bei jeder Maßnahme genau zu prüfen sind.
Literatur
1.
2.
3.
4.
Loney, Kevin. Oracle Database 10g. Die umfassende Referenz; Hanser 2005
Haas, Frank. Oracle-Tuning in der Praxis München; Hanser 2005
http://www.oracle.com/pls/db102/homepage
http://www.tpc.org/tpch/
Herunterladen