Database Tuning & Administration

 
WEITER LESEN
Database Tuning & Administration
Universität Konstanz                                            SS 2007
Fachbereich
Informatik und Informationswissenschaft

                                      Hausarbeit

                       Database Tuning & Administration

Seminar:            Seminar: Database Tuning & Administration
Dozent:             Prof. Dr. Marc H. Scholl
Assistant           Christian Gruen
Vorgelegt von:      Ketevan Karbelashvili & Irina Andrei

                                           1
Database Tuning & Administration
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
Database Tuning & Administration
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 DB-
Systeme 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 DB-
Systeme 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
       [5] Realisierung des TPC-H-Schemas auf einem Oracle-Datenbanksystem
2
       [6] TPC-H Schema erstellen
3
       [7] Datenbank Lizenzen

                                                            3
Database Tuning & Administration
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

       @ /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
Database Tuning & Administration
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
Database Tuning & Administration
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 Oracle-
Prozessen. 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
       [8] Datenbanksystem
6
       [9] Oracle-Datenbankadministration für SAP
7
       [10] Oracle Konfigurationsoptionen
8
       [9] Oracle-Datenbankadministration für SAP

                                                    6
Database Tuning & Administration
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
                        9
     •   LOG_BUFFER

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] Oracle Konfigurationsoptionen
10
         [11] Oracle-Server Bestandteile
11
         [12] http://www.adp-gmbh.ch/ora/concepts/cache.html
12
         [11] Oracle-Server Bestandteile

                                                               7
Database Tuning & Administration
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
Database Tuning & Administration
•   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
Database Tuning & Administration
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   DB_KEEP_CACHE_SIZE = 25M   schlechter als die
Ergebnisse der Standart DB_KEEP_CACHE_SIZE waren.

                                                10
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

                                                               02:52.8

                                                        Zeit
                                                               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
           [13] http://de.wikipedia.org/wiki/Sicht_%28Datenbank%29
16
           [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       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)
PARTITION BY HASH (p_size)
PARTITIONS 3
STORE IN (data1, data2, data3);

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 RANGE-
LIST- 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 nicht-
partitionierten 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äfix-
Index 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                                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,

18
           [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             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)
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 Index-
Cluster, 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
          [18] Oracle – Datenbanken Administration und Management
21
          [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              INTEGER NOT NULL,
              PS_SUPPKEY                       INTEGER NOT NULL,
              PS_AVAILQTY                      INTEGER NOT NULL,
              PS_SUPPLYCOST                    DECIMAL(15,2) 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_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)

DB_BLOCK_SIZEWert 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)

KCBH, UB4, KTBBH, KTBIT, KDBH   Werte erhält man aus der Data Dictionary Tabelle V$TYPE_SIZE
select * from v$type_size;

KCBH    BLOCK COMMON HEADER                20 Byte
UB4     UNSIGNED BYTE                      4 Byte
KTBBH   TRANSACTION FIXED HEADER           48 Byte
KTBIT   TRANSACTION VARIABLE HEADER        24 Byte
KDBH    DATA HEADER                        14 Byte

INITRANS  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.

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                LINEIETEM, ORDERS   und   NATION, SUPPLIER   zu
benutzen:

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
Sie können auch lesen