...

MariaDB Page Compression: Speicherplatz sparen mit minimalen Performanceeinbußen

MariaDB Page Compression reduziert den physischen Speicherbedarf, indem InnoDB-Seiten vor dem Schreiben auf Datenträger komprimiert werden und so I/O-Mengen spürbar sinken. Ich zeige, wie Sie Speicher sparen und die Latenz gering halten, welche Voraussetzungen gelten und welche Einstellungen in der Praxis am meisten bewirken.

Zentrale Punkte

Diese kompakten Stichpunkte führen in die wichtigsten Aspekte ein.

  • Seitenweise Kompression senkt Platzbedarf und I/O.
  • Unkomprimierter Buffer-Pool begrenzt CPU-Last im RAM.
  • Flexible Aktivierung pro Tabelle mit PAGE_COMPRESSED.
  • Dateisystem-Support für Sparse/Hole Punching ist Pflicht.
  • Algorithmuswahl steuert Rate, Latenz und CPU-Kosten.

Wie InnoDB Page Compression technisch arbeitet

Ich komprimiere jede InnoDB-Seite kurz bevor sie auf die Platte gelangt, sodass der Tablespace nur die tatsächlich reduzierten Bytes belegt und das Dateisystem freie Bereiche als Sparse markiert. Im Buffer-Pool halte ich Seiten weiterhin unkomprimiert, was die CPU-Kosten im Arbeitsspeicher gering hält und häufige Lesezugriffe schnell bleiben. Standardmäßig besitzen InnoDB-Seiten 16K, doch die gespeicherten Blöcke fallen nach der Kompression variabel kleiner aus, was besonders bei Text- oder JSON-Feldern viel Platz einspart. Beim Lesen entpacke ich die Seite direkt nach dem Laden ins RAM, also genau an der I/O-Grenze, wo die Einsparung bei der Übertragung am meisten zählt. So verlagere ich Last von I/O zur CPU, aber nur an den Stellen, an denen sie vertretbar ist.

Page Compression vs. klassische InnoDB-Tabellenkompression

Die klassische Kompression setzt auf ROW_FORMAT=COMPRESSED plus KEY_BLOCK_SIZE, was ein fixes komprimiertes Seitenformat erzeugt und beim Schreiben oder Aktualisieren eine zusätzliche Entscheidungslast bringt. Ich bevorzuge die Page Compression, weil sie flexibel bleibt: Gelingt eine Kompression nicht, kann InnoDB die Seite unkomprimiert ablegen, ohne das gesamte Dateiformat zu ändern. Der Buffer-Pool arbeitet weiterhin mit unkomprimierten 16K-Pages, was Cache-Treffer schnell macht und die CPU-Pfade einfach hält. Bei typischen OLTP-Workloads mit vielen Inserts und moderaten Updates liefert Page Compression eine bessere Balance aus Platzersparnis und Latenz. Im Ergebnis erhalte ich oft den spürbaren I/O-Vorteil, ohne einen hohen Overhead bei jedem Update zu riskieren.

Voraussetzungen und Grundkonfiguration

Für Page Compression setze ich InnoDB voraus und aktiviere innodb_file_per_table, damit jede Tabelle ihren eigenen Tablespace nutzt. Entscheidend ist das Dateisystem: Es muss Sparse-Dateien und Hole-Punching beherrschen, was bei ext4 und XFS gegeben ist und in modernen Cloud-Volumes in der Regel vorhanden ist. Für die Wahl des Algorithmus steuere ich innodb_compression_algorithm, typischerweise zlib, lz4 oder lzo, je nach gewünschter Rate und CPU-Profil. Wer die Storage-Schicht abwägt, profitiert von einem kompakten Dateisystem-Vergleich und berücksichtigt dabei auch Treiber- und Volume-Optionen. So entsteht eine Konfiguration, die Platz spart, I/O reduziert und verlässlich arbeitet.

Aktivierung auf Tabellenebene

Ich schalte Page Compression pro Tabelle scharf, afterdem die globalen Variablen stimmen, damit ich gezielt genau die Datensätze adressiere, die den größtmöglichen Nutzen bringen. Für neue Tabellen setze ich die Optionen direkt in der DDL, bei bestehenden Tabellen erledigt ein ALTER TABLE die Umstellung durch Neuschreiben. Die Kompressionsstufe definiere ich mit PAGE_COMPRESSION_LEVEL, das Verhalten hängt vom verwendeten Algorithmus ab. Weil die Umstellung Zeit kostet, plane ich Wartungsfenster ein und prüfe den Platzbedarf mit und ohne Kompression anhand realer Datenausschnitte. So kontrolliere ich Aufwand und Ergebnis ohne Überraschungen.

CREATE TABLE log_entries (
    id BIGINT UNSIGNED PRIMARY KEY,
    created_at DATETIME NOT NULL,
    level VARCHAR(20),
    message TEXT
) ENGINE=InnoDB
  PAGE_COMPRESSED=1
  PAGE_COMPRESSION_LEVEL=6;

ALTER TABLE log_entries
  ENGINE=InnoDB,
  PAGE_COMPRESSED=1;

Speicherersparnis in der Praxis

Je homogener und textlastiger die Daten, desto besser wirkt die Kompression; Log- und Reporting-Tabellen liefern meist deutliche Effekte. In typischen Workloads sehe ich oft 40–60 % weniger belegten Speicher mit zlib, während lz4 viele Fälle mit 30–50 % bedient und dafür mehr Durchsatz übrig lässt. Stark verteilte Binärdaten bringen weniger, doch auch dort reduzieren sich I/O-Mengen und Kosten oft merkbar. Ich teste immer mit Produktionsschnappschüssen auf Staging, um aussagekräftige Quoten zu gewinnen und Latency-Spitzen zu erkennen. Das Ergebnis: weniger Daten auf dem Datenträger, kürzere Transferzeiten, bessere Skalierung.

Performance: I/O vs. CPU richtig bewerten

Ich prüfe zuerst, ob der Engpass auf dem Datenträger oder auf der CPU liegt, denn davon hängt die Wahl der Kompressionsmethode ab. In I/O-limitierten Umgebungen sinken Lese- und Schreibmengen deutlich, sodass die effektive Leistung steigt, oft mit nur 5–10 % Zusatzlast gegenüber unkomprimierten Tabellen bei schnellen Algorithmen. CPU-limitierte Systeme profitieren von lz4 oder lzo, die sehr schnell arbeiten und nur etwas geringere Raten erreichen. Zusätzlich beachte ich den Doublewrite-Buffer, weil er das Schreibverhalten beeinflusst und zusammen mit Page Compression die I/O-Charakteristik formt. Da der Buffer-Pool unkomprimiert bleibt, wirken sich häufige Cache-Treffer kaum auf die Latenz aus.

Algorithmuswahl und Kompressionslevel

Ich entscheide die Algorithmus-Frage anhand von Datenmustern, Lese-/Schreibrate und CPU-Spielraum, statt mich nur an der Kompressionsquote zu orientieren. Zlib liefert oft die höchste Platzersparnis bei moderater Rechenarbeit, während lz4/lzo mit geringer Latenz glänzen. LZMA oder bzip2 nutze ich vor allem für Archive oder selten veränderte Tabellen, da die CPU-Kosten höher sind. Die Kompressionsstufe (PAGE_COMPRESSION_LEVEL) regelt das Verhältnis zwischen Rate und Aufwand, jedoch mit abnehmendem Grenznutzen jenseits mittlerer Stufen. Eine kurze Messreihe mit dem echten Datensatz findet schnell das beste Niveau.

Algorithmus Typische Rate CPU-Kosten Eignung Hinweise
zlib 40–60 % Mittel Viele OLTP/Reporting-Tabellen Gute Balance aus Rate/Latenz
lz4 30–50 % Niedrig Hohe Durchsatzanforderungen Sehr schnelle Dekompression
lzo 30–50 % Niedrig Schreibintensive Workloads Geringe Latenz bei Inserts
lzma 50–70 % Hoch Archive/kalte Daten Für seltene Änderungen
bzip2 50–70 % Hoch Selektive Historien Langsam, gute Quote

Monitoring und Metriken im Blick behalten

Ich messe Durchsatz, Latenz, CPU-Auslastung und Buffer-Pool-Hitrate, weil nur die Gesamtsicht den tatsächlichen Effekt zeigt. Ein Absinken der I/O-Mengen bei gleichbleibender oder besserer Latenz signalisiert einen Treffer in der Konfiguration. Steigt die CPU-Auslastung über ein gesundes Niveau, kontrolliere ich Algorithmus und Level und setze ggf. auf lz4 um. Zusätzlich beachte ich die Größe des Redo-Logs und das Checkpoint-Verhalten, da beides das Schreibprofil mitprägt. Langfristig erkenne ich Trends und kann proaktiv auf geänderte Workloads reagieren.

Backups und Wartung sauber planen

Voll- und inkrementelle Dateisicherungen profitieren von der geringeren Datenmenge, weil weniger Bytes kopiert werden, während logische Dumps ihre Größe meist behalten. Ich teste Restore-Zeiten mit realen Daten, damit ich die gewonnene Platzersparnis gegen die praktische Wiederherstellungsdauer abwägen kann. Änderungen am Algorithmus oder Level dokumentiere ich und prüfe Kompatibilität der Backup-Tools mit der eingesetzten MariaDB-Version. Außerdem validiere ich die Integrität nach großen ALTER TABLE-Operationen, gerade wenn viele Tabellen auf Page Compression umgestellt wurden. So bleibt die Wiederanlaufzeit vorhersagbar und die Sicherungsstrategie verlässlich.

Dateisystem und Storage-Ebene verstehen

Damit Sparse-Dateien greifen, benötigt das Dateisystem Hole-Punching, was bei ext4 und XFS verfügbar ist und in Hosting-Setups weit verbreitet ist. Ich achte auf Mount-Optionen und Queue-Depth, da sie die I/O-Kennlinien stark beeinflussen. Für ext4 überprüfe ich etwa Commit-Intervalle und Journal-Modi und berücksichtige, wie Garbage-Collection auf SSD/NVMe wirkt. Ein Blick auf passende ext4-Optionen hilft, die Page-Compression-Effekte mit den Eigenschaften des Dateisystems abzustimmen. So nutze ich den physischen Storage effizient und verhindere Nebenwirkungen.

Praxisleitfaden für die Einführung

Ich starte mit einer Testumgebung und kopiere repräsentative Produktionsdaten, um erste Messwerte für Quote, Latenz und Durchsatz zu erhalten. Danach aktiviere ich Page Compression zunächst bei großen, überwiegend lesenden Tabellen oder Archiven mit wenigen Updates. Die Ergebnisse bewerte ich anhand klarer Kennzahlen und vergleiche sie mit dem Ausgangszustand, bevor ich weitere Tabellen umstelle. Frühzeitige Kommunikation mit Applikationsteams verhindert Überraschungen bei Wartungsfenstern und sorgt für klare Erwartungen. Nach jeder Ausweitung passe ich Level und Algorithmus an, bis Speicherersparnis und Latenz im Zielkorridor liegen.

Kombination mit weiteren Optimierungen

Gute Indizes reduzieren die Zahl gelesener Seiten, daher prüfe ich Indexabdeckung und Kardinalitäten regelmäßig. Sauber formulierte Abfragen, passende Joins und der gezielte Einsatz von EXPLAIN senken I/O und halten die Cache-Trefferquote hoch. Eine ausreichend große Buffer-Pool-Größe verhindert unnötige Ladevorgänge von Disk und macht den Kompressions-Overhead im Hotset praktisch unsichtbar. Auf der Hardware-Seite zahlen sich SSDs und NVMe durch hohe IOPS und geringe Latenz aus, was die Vorteile der Page Compression verstärkt. In Summe spielt die Kompression mit Query-Design, Indexarbeit und Speicherausbau zusammen und formt so einen schlanken Datenpfad.

Kompatibilität, Versionen und Grenzen

Ich halte im Blick, welche Umgebung Page Compression unterstützt und wo Grenzen liegen. Auf verbreiteten Linux-Dateisystemen wie ext4 und XFS funktioniert Hole-Punching stabil. ZFS verhält sich anders: Da Punching dort nicht gleichwertig verfügbar ist, setze ich auf ZFS eher die native ZFS-Kompression ein und verzichte auf Page Compression. In Container-Setups mit OverlayFS binde ich das Datenverzeichnis vorzugsweise als Bind-Mount vom Host ein, damit Punching und Sparse-Dateien zuverlässig greifen. Außerdem kombiniere ich Page Compression nicht mit InnoDB-Tabellenverschlüsselung auf Dateiebene: Verschlüsselung macht die Daten für Kompressionsalgorithmen weitgehend zufällig und blockiert teils auch das Punching. Wer beides benötigt, setzt auf Volume-/Filesystem-Verschlüsselung unterhalb von InnoDB.

Bei der InnoDB-Seitengröße (innodb_page_size) bleibe ich meist bei 16K. Kleinere Seitengrößen können die Kompression erschweren und die Verwaltungs-Overheads erhöhen. Temporäre Tabellen oder MEMORY/Arbeitstabellen verändern sich durch Page Compression nicht – der Gewinn entsteht nur im jeweiligen .ibd-Tablespace.

Aktivierung, Deaktivierung und Rebuilds ohne Überraschungen

Die Umstellung per ALTER TABLE erzeugt immer einen Rebuild der Tabelle. Ich plane daher:

  • Wartungsfenster mit klaren SLAs und ausreichendem Speicherplatz für die temporäre Kopie.
  • Vorabprüfung mit EXPLAIN für ALTER, um das erwartete Vorgehen (INPLACE/COPY, LOCK-Level) zu sehen.
  • Optionale Batching-Strategie: erst große, selten veränderte Tabellen, danach mittlere, am Ende die heißen Tabellen – wenn überhaupt.

Zum Abschalten gehe ich symmetrisch vor und setze PAGE_COMPRESSED=0. Anschließend führe ich ein OPTIMIZE TABLE oder einen erneuten ALTER-Rebuild aus, damit der Tablespace wieder ohne Löcher geschrieben wird und der physische Platzverbrauch realistisch abgebildet ist.

Bulk Loads, Hot-Updates und Defragmentierung

Für Massendaten lade ich entweder direkt komprimiert, wenn I/O knapp ist, oder ich beschleunige den Import, indem ich unkomprimiert lade und danach mit ALTER TABLE auf PAGE_COMPRESSED umstelle. Anschließend erzwingt der Rebuild das optimale Layout mit maximaler Loch-Punching-Wirkung. Bei Tabellen mit sehr vielen In-Place-Updates plane ich regelmäßige Rewrites (OPTIMIZE TABLE oder Partition-Rollovers), weil sich durch wiederholte Änderungen die Kompressionsvorteile über die Zeit mindern können. Für BLOB/TEXT-Spalten setze ich auf ein zeitgemäßes Zeilenformat (z. B. DYNAMIC), damit große Off-Page-Daten effizient gehandhabt werden und die Seitennachbarschaft nicht unnötig wächst.

Wirksamkeit prüfen und belegen

Ob Page Compression greift, verifiziere ich mit einfachen Systemkommandos und MariaDB-Sichten:

# Apparente Größe vs. belegte Blöcke vergleichen
ls -ls --block-size=1 *.ibd
du -h --apparent-size *.ibd
du -h *.ibd

# Ausmaß der Lochbildung (Punching) pro Datei prüfen
filefrag -v your_table.ibd | tail -n +1

# In MariaDB: Tabellenstatus und DDL-Optionen prüfen
SHOW TABLE STATUS LIKE 'log_entries'\G
SHOW CREATE TABLE log_entries\G

Die apparente Größe (ls) bleibt beim logischen Datenvolumen, während du die tatsächlich belegten Blöcke zeigt. Eine spürbare Differenz signalisiert funktionierendes Hole-Punching. Ich korreliere diese Messung mit I/O-Metriken (Reads/Writes pro Sekunde, Warteschlangentiefe, Latenz) und der CPU-Auslastung, um den Gesamteffekt zu bewerten.

Backup-Details: Sparse korrekt sichern und wiederherstellen

Damit Backups die Platzersparnis respektieren, achte ich auf Sparse-Unterstützung in den Werkzeugen. Beim Kopieren physischer Dateien nutze ich passende Schalter, damit Löcher nicht „gefüllt“ werden:

# Kopieren mit Erhalt von Sparse-Bereichen
cp --sparse=always source.ibd dest.ibd
rsync -S --progress source.ibd dest.ibd
tar --sparse -cvf backup.tar /var/lib/mysql/datadir

# Prüfen, ob das Ziel weiterhin Sparse ist
du -h dest.ibd
ls -ls dest.ibd

Bei Snapshot-Backups (z. B. auf Block-Device-Ebene) ist die Ersparnis je nach Anbieter unterschiedlich relevant. Für logische Dumps (mysqldump, mariadb-dump) ändert sich die Exportgröße kaum, jedoch sinken Restore-Zeiten, wenn der anschließende Rebuild wieder Page Compression aktiviert und damit die I/O-Mengen beim Neuaufbau reduziert.

Replikation, HA und Rollouts im Betrieb

Page Compression wirkt transparent für Replikation und Binlogs, denn repliziert werden SQL-Änderungen, nicht die komprimierten Seiten. Ich rolle DDL-Änderungen bevorzugt zuerst auf Replikas aus und beobachte Latenz und I/O, bevor ich den Primärserver umstelle. Bei Multi-Source- oder Kaskaden-Topologien achte ich darauf, dass überall ein passender Algorithmus (innodb_compression_algorithm) gesetzt ist, damit identische DDL das gleiche Verhalten erzielt. Für Zero-Downtime-Rollouts kombiniere ich die Umstellung mit Switchover/Failover-Plänen.

Tieferes Tuning: I/O-Profile und Checkpoints

Weil Kompression die Anzahl und Größe der zu schreibenden Blöcke verändert, stimme ich InnoDBs I/O-Parameter auf das neue Profil ab. Eine realistische innodb_io_capacity (und *_max) hilft, saubere Checkpoints zu erzeugen, ohne plötzliche Flush-Spitzen. Ich prüfe, ob der Doublewrite-Buffer mit der neuen Schreibcharakteristik harmoniert, und überwache das Verhältnis aus dirty pages und fsync-Rate. Auf Geräten mit hoher Parallelität (NVMe) skaliere ich die Write-Threads und die Queue-Tiefe des Blockgeräts, damit die geringere Datenmenge als echte Latenzreduktion ankommt.

Problembehebung und typische Stolpersteine

  • CPU-Spitzen nach Aktivierung: Algorithmus auf lz4/lzo wechseln oder PAGE_COMPRESSION_LEVEL moderat senken, Hotsets im Buffer-Pool vergrößern.
  • I/O sinkt, aber Latenz schwankt: Checkpointing und Dirty-Page-Quote prüfen; zu kleine Redo-Logs führen zu häufigen Flushes.
  • Unerwartet geringe Platzersparnis: Datenstruktur prüfen (viele binäre/zufällige Felder), Rebuild erzwingen, BLOB/TEXT-Muster analysieren, ggf. auf zlib wechseln.
  • Kein Effekt auf Dateigröße: Hole-Punching-Unterstützung des Dateisystems kontrollieren, Container-Layer vermeiden, Sparse-Kopie nicht „entsparsifizieren“.
  • Heiß beschriebene Tabellen: Page Compression selektiv einsetzen; Alternativen prüfen (nur Archiv-/Log-Tabellen komprimieren).

Praxisnahe Konfigurationsbeispiele

Für einen sauberen Start halte ich die globale Konfiguration knapp und steuerbar:

[mysqld]
innodb_file_per_table=1
innodb_compression_algorithm=zlib   # oder lz4/lzo je nach Profil
# weitere I/O-Parameter passend zur Plattform anpassen
# innodb_io_capacity=...
# innodb_io_capacity_max=...

Pro Tabelle definiere ich die Kompression explizit, um keine ungewollten Seiteneffekte zu erzeugen. Nach großen Imports oder vielen Updates setze ich gezielt OPTIMIZE TABLE ein, um Löcher neu zu kalibrieren und das über die Zeit entstandene Fragment zu reduzieren.

Kurz zusammengefasst

InnoDB Page Compression reduziert den Speicherverbrauch spürbar und verschiebt Last von I/O zur CPU, ohne den Buffer-Pool zu verändern. Gut gewählte Algorithmen wie lz4 oder zlib liefern in vielen Workloads 30–60 % Einsparung und bleiben bei der Latenz im grünen Bereich. Entscheidend sind ein Dateisystem mit Hole-Punching, innodb_file_per_table und eine saubere Aktivierung auf Tabellenebene. Wer Tests mit echten Daten fährt, Monitoring einbindet und Level sowie Algorithmus feinjustiert, erreicht dauerhaft geringe Kosten bei verlässlicher Performance. So sparen Sie Platz, halten Ihre Systeme flink und gewinnen Reserven für wachsende Datensätze.

Aktuelle Artikel

Linux Server mit visualisierten Pressure Stall Information Kennzahlen im Rechenzentrum
Administration

Linux PSI für präzise Performanceanalyse und Monitoring

Linux PSI (Pressure Stall Information) macht sichtbar, wie stark CPU, Speicher und I/O dein System ausbremsen. Erfahre, wie du PSI aktivierst und für präzises Performance monitoring einsetzt.