MySQL CompressionHello folks, we all know the benefits of table compression in MySQL, with current technology, processing speed, and compression disks, and in most cases, it is a benefit.

Now, what happens when that doesn’t happen?

In this simple blog, I’m going to show you something interesting that happens when you try to transition from a compressed table to a normal one. We are not going to talk in detail or discuss anything else such as: why should it be bad that the table is compressed? What is the performance, system performance, not even what penalty of hardware resources the compression requires?  We are also not going to talk about whether the pages in memory are compressed, uncompressed, or both. This has been talked about enough and there are some very interesting blogs that you can find on our site or even in the documentation itself.

What I am going to show you is something very curious, and for this, we are going to carry out the exercise from the beginning to the end in such a way that you can do it yourself (well, except for the data loading part, heh!) and I’ll give an example script (later).

Let’s create the table in a database instance with Percona Server for MySQL 5.7 installed.

After that, let’s load the table with some data (100,000 rows).

Let’s verify the size of the table (previously doing an ANALYZE TABLE with innodb_stats_persistent_sample_pages=100000 so that the statistics are as realistic as possible).

Next, we are going to compress the table with a KEY_BLOCK_SIZE=4 (this size was chosen arbitrarily, at no time is it indicated or decided whether or not it is the optimal value, in fact, it is not).

We verify the size of the table again (previously doing an ANALYZE TABLE with innodb_stats_persistent_sample_pages=100000 so that the statistics are as realistic as possible).

As you can see, the table has been compressed, let’s check its structure.

How do we reverse the compression? Good question. It should be easy, right?

(Clarification, before you ask, we are not going to judge how it should be done based on the size of the tables, what impact this ALTER would have on replication, and other things, the idea is to show how to reverse it and nothing else.)

We could use this command, let’s see:

It seems to have worked! Uncompressed it:

Better check:

Something is wrong! the KEY_BLOCK_SIZE is still 4.

Second attempt:

Better check:

Something is wrong! Both the primary key and the secondary indexes continue to show KEY_BLOCK_SIZE=4.

Although when the table is converted from compressed to uncompressed, internally the KEY_BLOCK_SIZE of the indices honors that of the table, the CREATE TABLE statement does not. This would be an aesthetic/cosmetic issue at first, but it is a real problem when you do a dump since the CREATE TABLE is left with the KEY_BLOCK_SIZE values, which is not good.  Here is the output of mysqldump:

As you can see, there seems to be no way to reverse the KEY_BLOCK_SIZE in the table definition index-wise with a global ALTER TABLE command (if we can call it that), so we’ll make this last attempt:

And now, it has the correct definition without the KEY_BLOCK_SIZE:

Apparently, there are bugs in MariaDB related to the case:

https://jira.mariadb.org/browse/MDEV-26400

https://jira.mariadb.org/browse/MDEV-11757

A similar one in MySQL:

https://bugs.mysql.com/bug.php?id=56628

In MySQL 8, the situation is as follows:

Let’s execute the ALTER to compress the table:

Let’s check again:

So far everything is the same as in MySQL 5.7: the KEY_BLOCK_SIZE persists in the definition of the entire table, but not of the indexes.

Fortunately, by running this command, we effectively reversed everything:

As always, we recommend doing a preliminary test in a development environment before running it in production.

Conclusion

In MySQL 5.7, the only way to completely revert (at least in the definition of the table and its indexes) is to regenerate both the primary key and all its indexes.  It sounds like a terminal solution, but if you make backups using mysqldump (we always recommend using Percona XtraBackup for these purposes, it’s faster and more efficient) it is an issue to take into account since in its definition it preserves those erroneous definitions. Fortunately, this is fixed in MySQL 8.

Interesting, isn’t it?

Subscribe
Notify of
guest

2 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments

Other related MySQL bugs:

This looks solved in MySQL 8.0, but what about upgrading an installation where a table has been ALTERed in such way ?

Fernando Mattera

Hello Jean-Francois,

Thank you so much for his comment. Could you please elaborate a bit more on your question? Are you telling me to tell the client to upgrade to MySQL 8, or are you telling me what could happen if I use that MySQL 5.7 fix, and some time later we migrate to MySQL 8, what happens to the destination of the table.