MariaDB table compression can drastically reduce your storage footprint, but its primary benefit isn’t just saving disk space; it’s about improving I/O performance by reading less data from disk.
Let’s see it in action. Imagine a simple users table:
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
email VARCHAR(100) UNIQUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Populating it with some data:
INSERT INTO users (username, email) VALUES
('alice', 'alice@example.com'),
('bob', 'bob@example.com'),
('charlie', 'charlie@example.com');
-- ... imagine millions of rows
Without compression, this table on disk might consume, say, 100MB. After enabling compression, the same data might only take up 30MB. This means during a SELECT * FROM users WHERE id = 123; query, MariaDB only needs to read 30MB from disk instead of 100MB. The CPU cost of decompressing that 30MB is usually far less than the time saved by reading less data.
The core mechanism behind MariaDB’s table compression lies in its storage engines, primarily InnoDB. When you enable compression, InnoDB doesn’t just compress the entire table file into a single block. Instead, it compresses data page by page. A page is the fundamental unit of I/O for InnoDB, typically 16KB. When a page is full and needs to be written to disk, InnoDB attempts to compress it. If the compressed page is smaller than the original, it’s stored in its compressed form. When that page is read back into memory, it’s decompressed on the fly by the InnoDB buffer pool.
There are several levers you can pull to control compression behavior:
innodb_file_per_table: This is a prerequisite. You must setinnodb_file_per_table = 1(which is the default in modern MariaDB versions) for table-level compression to work. Each table gets its own.ibdfile, allowing for granular compression settings and management.innodb_page_size: While not directly a compression setting, a smaller page size (e.g., 4KB or 8KB) can sometimes lead to better compression ratios if your rows are small, as it reduces internal fragmentation within pages. However, it also increases the number of pages and can impact performance for large rows. The default is 16KB.innodb_compression_algorithm: This specifies the compression algorithm to use. Common options includeinnodb(which uses zlib by default),lz4, andzstd.lz4andzstdgenerally offer much faster compression/decompression speeds than zlib, often with comparable or even better compression ratios.innodb_compression_level: For theinnodb(zlib) algorithm, this controls the compression level (1-9). Higher levels mean better compression but more CPU usage.lz4andzstdhave their own levels, but the default is usually a good balance.
To enable compression for an existing table, you can use ALTER TABLE:
ALTER TABLE users COMPRESSION = 'lz4';
This command will rebuild the table, compressing each page using the lz4 algorithm. For new tables, you can specify compression during creation:
CREATE TABLE products (
product_id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
description TEXT,
price DECIMAL(10, 2)
) COMPRESSION = 'zstd';
The most surprising true thing about MariaDB table compression is that it’s not just about saving disk space; it can actually speed up your queries by reducing the amount of data that needs to be physically read from disk. This is often counterintuitive because compression is typically associated with a CPU overhead. However, for I/O-bound workloads, the time saved by reading less data from slower storage frequently outweighs the CPU cycles spent on decompression. This effect is amplified on slower storage like HDDs or over networks.
The primary way to disable compression on a table is to ALTER it with COMPRESSION = 'none'.
ALTER TABLE users COMPRESSION = 'none';
This will rebuild the table, decompressing all pages. You’ll also want to ensure innodb_file_per_table is set to 1 in your my.cnf or mariadb.conf file to enable this feature.
The next logical step after optimizing storage with compression is to consider how MariaDB handles data in memory, specifically the InnoDB buffer pool.