Auf den ersten Blick könnte man meinen, das Thema Datenkompression sei alles andere als aktuell. Schließlich spielt eingesparter Plattenplatz bei Datenbank-Anwendungen heute dank stetig sinkender Storage-Kosten kaum mehr eine finanzielle Rolle. Plattenkapazitäten von Hunderten von GByte sind billigst zu haben, und Speicherträger können jederzeit leicht an bestehende Systeme angedockt werden. Warum also sollte man Daten noch komprimieren?
Tatsächlich ist Datenkompression bei wenigen GByte Datenaufkommen kaum relevant. Bewegt sich der Storage-Bedarf hingegen – wie in professionellen IT-Umgebungen üblich – in größeren Dimensionen, bedeutet Speicherminimierung durchaus wirtschaftliche Vorteile. Das gilt etwa für Datenbanken mit fünf oder zehn TByte, wie sie heute bei Data-Warehouse-Systemen, aber auch anderen Datenbank-Anwendungen, üblich sind.
Doch reduzierte Speicherkosten sind nur ein Aspekt, warum es sich lohnt, Daten möglichst sparsam abzulegen. Zu bedenken ist auch, dass eine optimierte Datenspeicherung die Ressourcen, die für das Management der Daten verwendet werden, schont. Je weniger Daten gespeichert werden, umso geringer sind beispielsweise die Anforderungen an die Datenbank-Server. Die Performance des Systems wird verbessert, Zugriffzeiten verringert und die IO-Last ganz allgemein minimiert. Kurz gesagt: Je weniger Daten, umso effizienter arbeitet das Datenbank-System.
Der Wunsch von Anwendern ist daher groß, die Fähigkeiten von Datenbank-Systemen zu nutzen, um große Datenmengen durch eine möglichst effiziente Speicherung zu minimieren. Wir stellen Ihnen in diesem Artikel verbreitete Techniken vor, um Daten in SQL-Datenbanken effizient zu speichern. Den Schwerpunkt bildet dabei die Tabellenkompression und im Teil 2 die Indexkompression.
Textdaten – Umstieg auf Unicode
Verfolgt man das Ziel einer „ganzheitlichen“ Senkung des Speicherbedarfs, spielen neben der eigentlichen Datenkompression schon ganz simple Aspekte eine Rolle. Beispielsweise die Frage, wie effizient eine Datenbank textliche und numerische Werte speichert.
Textdaten werden heute meist im Unicode-Zeichencode gespeichert. Im Gegensatz zu früheren Zeichenkodierungen, welche in der Regel nur ein bestimmtes Schriftsystem kodierten, ist es das Ziel von Unicode, alle in Gebrauch befindlichen Schriftsysteme und Zeichen abzubilden.
Viele Datenbank-Produkte basieren heute auf Unicode. So setzen beispielsweise einige SAP-Installationen wie das SAP Portal bereits zwingend Unicode voraus. Ab dem nächsten SAP ERP Release 2010 unterstützt SAP nur noch Unicode-basierte Systeme.
Unicode wirkt sich leider negativ auf den Storage-Bedarf aus – CPU- und RAM-Ressourcen werden durch Unicode stärker ausgelastet. Wie stark der Storage-Bedarf tatsächlich steigt, hängt jedoch wesentlich vom verwendeten Unicode-Zeichensatz ab.
Eingesetzt werden bei Datenbanken in der Regel das Unicode Transformation Format UTF-8 und UTF-16. Dabei ist UTF-8 das gebräuchlichere und wird beispielsweise im Internet und in fast allen Betriebssystemen verwendet. Der entscheidende Unterschied zwischen beiden Zeichensystemen ist, dass UTF-8 für die meisten Buchstaben des lateinischen Alphabets nur ein Byte für die Kodierung verwendet. Weniger gebräuchliche Zeichen wie die deutschen Umlaute belegen zwei Byte. Für das relativ neue Euro-Zeichen fand man nur noch eine Kodierung mit drei Byte. Exotische Symbole wie der Violinschlüssel belegen bis zu vier Byte.
Neben UTF-8 hat UTF-16 aber ebenfalls eine große Bedeutung, zum Beispiel als Zeichenkodierung in Java. UTF-16 kodiert standardmäßig mit zwei Byte. Damit lassen sich dann rund 65.000 der häufigsten weltweit benutzen Zeichen darstellen. Für exotische antike oder fernöstliche Zeichensätze weicht UTF-16 auf vier Byte aus.
UTF-8 statt UTF-16
Westeuropäische Texte, Namen und Produktbezeichnungen kodiert UTF-8 mit durchschnittlich etwas mehr als einem Byte pro Zeichen. Damit ist UTF-8 wesentlich kompakter als UTF-16, das dafür zwei Byte pro Zeichen benötigt. Das folgende Beispiel vergleicht den unterschiedlichen Storage-Bedarf von ASCII, UTF-8 und UTF-16.
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
Benötigter Platz |
|
ASCII |
G |
Ö |
T |
T |
I |
N |
G |
E |
N |
9 Byte |
|||||||||
UTF-8 |
G |
Ö |
T |
T |
I |
N |
G |
E |
N |
10 Byte |
|||||||||
UTF-16 |
G |
Ö |
T |
T |
I |
N |
G |
E |
N |
18 Byte |
Migriert man eine Datenbank mit vielen textuellen Daten von ASCII nach Unicode UTF-16, wächst deren Platzbedarf typischerweise um 40 bis 60 Prozent. Bei UTF-8 ergibt sich nur ein Wachstum von rund zehn Prozent.
Da UTF-8 eine wesentliche Verringerung des Plattenplatzbedarfs zur Folge hat und im Vergleich zu UTF-16 keine Performance-Nachteile bestehen, sollte aus Speichereffizienzperspektive grundsätzlich UTF-8 verwendet werden. Leider unterstützen nicht alle Datenbank-Systeme UTF-8; die Tabelle am Ende des zweiten Teils der Artikelserie liefert hierzu Informationen.
Numerische Werte effizient speichern
Auch bei numerischen Werten kann der Speicherplatzbedarf durch simple Techniken verringert werden. Eine Möglichkeit, die bei Oracle, DB2 und dem MS SQL Server genutzt werden kann, ist, numerische Werte mit variablen Feldgrößen abzuspeichern. Die folgende Tabelle demonstriert den Unterschied, der vor allem bei einem kleinen Wertebereich ins Gewicht fällt.
Datentyp |
Number |
Number |
Number |
Number |
Wertebereich |
0-5000 |
0-1000 |
0-5 |
0-365 |
Platzbedarf bei fester Feldgröße |
5 Byte |
5 Byte |
5 Byte |
5 Byte |
Typischer Platzbedarf bei variabler Feldgröße |
2-4 Byte |
2-4 Byte |
2 Byte |
3 Byte |
Erfahrungen haben gezeigt, dass bei der Speicherung numerischer Werte mit variablen Feldgrößen Einsparungen zwischen 30 und 50 Prozent des Plattenplatzes möglich sind. Die konkreten Werte hängen von der Datenbank-Größe und -Struktur ab.
Die bislang vorgestellten Methoden sind allerdings keine Kompressionstechniken im engeren Sinn, sondern lassen sich unter effizienter Speicherung textlicher und numerischer Daten subsumieren.
Mehrfach vorkommende Daten eliminieren – Tabellenkompression
Spricht man von Komprimierung, meint man in der Regel Tabellenkompression. Tabellenkompression ist eine seit mehreren Jahren übliche Methode, den Speicherbedarf in strukturierten Daten zu reduzieren. Dabei wird die Tatsache genutzt, dass selbst bei hoch normalisierten relationalen Datenbanken in einigen Attributen gleiche Werte in mehreren Datensätzen auftreten. Beispiele sind Felder mit eingeschränktem Wertebereich wie „Farbe“, „Geschlecht“ oder „Status“. Besonders viele Mehrfacheinträge befinden sich jedoch in schwach normalisierten Tabellen, wie sie im Data-Warehouse-Umfeld aus Performance-Gründen üblich sind.
Bei der Tabellenkompression wird Speicherplatz gespart, indem Mehrfacheinträge in einer Tabelle nur einmal abgelegt werden. Werte, die sich wiederholen, werden in einer eigenen Symboltabelle auf Blockebene gespeichert. An Stelle der sich wiederholenden Daten steht dann im jeweiligen Datensatz nur noch ein Zeiger auf diese Tabellenstruktur. Damit erfolgt praktisch eine automatische Normalisierung durch Zusammenfassen aller Mehrfacheinträge von Datenfeldern im Datenbank-Block.
Die Abbildung zeigt den Table Compress anschaulich anhand eines Beispiels mit fünf Datensätzen.
Die Komprimierung erfolgt beim Einfügen von Daten in die Tabelle. Die Platzersparnis ergibt sich aus der Verwendung der Zeiger, die weniger Speicherplatz als die Datenwerte erfordern. Dabei verringert sich nicht nur der Speicherplatzbedarf auf der Festplatte und im RAM, sondern es erhöht sich auch die Performance der Tabellenzugriffe. Der Komprimierungsalgorithmus ist sehr effizient, der CPU-Verbrauch für die Komprimierung beziehungsweise Dekompression gering. Für den Anwender ändert sich beim Zugriff auf die Daten nichts. Die Kompression ist für ihn vollständig unsichtbar.
Tabellenkompression einrichten
Grundsätzlich erfolgt die Datenkompression beim Schreiben. Die Blöcke werden jedoch nicht bei jeder Schreiboperation komprimiert, sondern im Batch-Modus. Datenmengen, die kleiner als ein Block sind, werden nicht komprimiert.
Unter Oracle 11g kann die Komprimierung einer Tabelle bei der Erstellung mit der Option „Compress“ angefordert werden: CREATE TABLE tab-name ..... COMPRESS
;
Eine bereits bestehende Tabelle lässt sich wie folgt komprimieren: ALTER TABLE tab-name MOVE COMPRESS
;
Dabei wird eine neue Tabelle mit der Eigenschaft COMPRESSION
angelegt. Anschließend werden die Daten komprimiert eingefügt, die alte Tabelle wird gelöscht und die neue umbenannt.
Sollen Daten in eine bereits komprimierte Tabelle eingefügt werden, sollte dies immer mit DIRECT PATH
erfolgen. Ein normales Einfügen mit INSERT
oder SQL*LOADER
führt zu fast keiner Komprimierung.
Ein möglicherweise entscheidender Nachteil der Tabellenkompression ist folgender: Werden die Daten einer komprimierten Tabelle nachträglich geändert, führt dies zu einer Dekompression. Nach der Änderung werden die Datensätze in unkomprimierter Form wieder eingefügt. Die angestrebte Platzersparnis geht dann verloren. Eine Tabellenkompression ist also nur dann sinnvoll, wenn die Daten vorrangig nur noch gelesen werden.
Der folgende Befehl macht die Komprimierung rückgängig: ALTER TABLE tab-name MOVE NOCOMPRESS
;
Eine weitere Möglichkeit der Tabellenkompression ist die Definition auf TABLESPACE- und Partitionsebene. Bei Definition auf TABLESPACE-Ebene erben alle Tabellen die Kompressionseigenschaft.
Tabellenkompression – Effekt Speicherreduktion
Platzersparnis und Performance-Gewinn sind die beiden wesentlichen Ziele der Kompression. Wie stark die Kompression den Speicherbedarf reduziert, hängt von den jeweiligen Daten ab. Datenbanken mit vielen redundanten Informationen oder großen Datenbank-Blockgrößen profitieren stärker von der Komprimierung.
Als grobe Vorabschätzung kann bei durchschnittlich redundanten Tabellen mit 50 Prozent Platzersparnis gerechnet werden. Im Data-Warehouse-Bereich, in dem hoch redundante Tabellen üblich sind, werden deutlich höhere Komprimierungsraten erreicht. So stellte 2003 der Oracle-Kunde OfficeMax fest, dass Tabellenkompression im SAP Business Information Warehouse (SAP BW) eine Platzeinsparung von 70 Prozent bringt.
Ein ähnliches Ergebnis brachte die Komprimierung eines 5-TByte-Systems, das als Scalability Showcase der SAP auf der SAPphire 2002 diente. Heute werden im Data-Warehouse-Umfeld bei hoch redundanten Tabellen Komprimierungsraten von mehr als 85 Prozent erreicht. Das bedeutet, dass die komprimierte Tabelle achtmal kleiner ist als die unkomprimierte.
Kein Wunder also, dass Datenkompression besonders in Business-Intelligence-Anwendungen eine große Rolle spielt. Entsprechend zählt das Whitepaper „Oracles Top Ten Features for Large Scale Data Warehousing“ die Tabellenkompression zu den Top Ten Features und „essential feature for a data warehousing platform“. Beispielapplikationen erreichen demnach sogar eine Komprimierungsrate vom Faktor 12.
Einige Statistiken, was Komprimierung beim Erstellen, Einfügen und Ändern von Daten genau bringt, finden Sie in der Trivadis-Studie „Einsetzbarkeit von Table Compression im Data-Warehouse-Umfeld“.
Tabellenkompression – Effekt Performance-Gewinn
Auch der Performance-Gewinn lässt sich nicht allgemein beziffern, sondern hängt von den Besonderheiten der Datenbank ab. Grundsätzlich gilt: Zum Komprimieren und Dekomprimieren der Daten braucht es einerseits CPU-Leistung. Andererseits müssen weniger Datenblöcke auf die Festplatten geschrieben und von dort geholt werden.
Die Trivadis-Studie beziffert die CPU-Belastung beim Schreiben genauer anhand einer Data-Warehouse-Beispielapplikation im Terabytebereich mit Tabellen bis zu 100 Millionen Zeilen. So wird durch Komprimierung bei Einfügeoperationen rund doppelt so viel CPU-Zeit benötigt wie ohne. Bei Änderungsoperationen beträgt der CPU-Bedarf etwa 40 Prozent mehr, bei Löschoperationen wird die CPU nicht zusätzlich belastet. Der IO-Bedarf verringert sich beim Einfügen und Löschen je nach Kompressionsfaktor um etwa 30 Prozent.
Ein Performance-Gewinn ergibt sich besonders beim Zugriff, also beim Lesen der komprimierten Daten. Die CPU wird hier kaum mehr belastet, die Abfrage-Performance verbessert sich laut Trivadis um etwa 10 Prozent. Doch es sind auch deutlich höhere Werte erzielbar.
Ein Projekt des IT-Dienstleisters Ordix AG hat beispielsweise gezeigt, dass die Antwortzeit in einer für Kompression gut geeigneten Tabelle deutlich sank. Für den Fall, dass die Daten vollständig von der Platte geladen werden mussten, reduzierte sich die Abfragezeit beispielsweise von 22 auf 5 Sekunden; für den Fall, dass sich die Daten schon im Puffer befinden, von 40 auf 33 Sekunden.
Ob eine Tabelle für Komprimierung gut geeignet ist, lässt sich anhand folgender Richtlinien prüfen.
-
Kandidaten für eine Komprimierung sind Tabellen mit vielen redundanten Informationen.
-
Dabei sollten die Daten mit Blockoperationen eingefügt werden.
-
Die Daten sollten weiter möglichst nur einmal geschrieben und dann nur noch gelesen werden.
Alle diese Kriterien werden idealerweise von Data-Warehouse-Datenbanken erfüllt. Nicht geeignet für Kompression sind Tabellen, bei denen die Daten über Einzeloperationen eingefügt oder durch Updates häufig verändert werden. Hier schadet die Kompression in ungünstigen Fällen mehr, als dass sie nützt. Auch auf indexorganisierte Tabellen ist das Kompressionsverfahren nicht anwendbar. Ärgerlich ist auch, dass die Struktur einer komprimierten Tabelle nicht mehr geändert werden kann.
Fazit
In diesem ersten Teil unseres Zweiteilers haben wir erläutert, wann sich die Kompression einer Datentabelle lohnt. Ein Manko der Tabellenkompression ist, dass sie nur bei lesendem Zugriff sinnvoll ist und den Update der Inhalte erschwert. So kommt sie vor allem im Data-Warehouse-Bereich zum Einsatz, wo große Datenmengen zur Analyse dauerhaft archiviert sind. (ala)