The short version

I created > one billion InnoDB tables in MySQL 8.0 (tables, not rows) just for fun. Here is the proof:

Yes, it took 6 hours and 57 minutes to count them all!

Why does anyone need one billion tables?

In my previous blog post, I created and tested MySQL 8.0 with 40 million tables (that was a real case study). The One Billion Tables project is not a real world scenario, however. I was challenged by Billion Tables Project (BTP) in PostgreSQL, and decided to repeat it with MySQL, creating 1 billion InnoDB tables.

As an aside: I think MySQL 8.0 is the first MySQL version where creating 1 billion InnoDB tables is even practically possible.

Challenges with one billion InnoDB tables

Disk space

The first and one of the most important challenges is disk space. InnoDB allocates data pages on disk when creating .ibd files. Without disk level compression we need > 25Tb of disk. The good news: we have ZFS which provides transparent disk compression. Here’s how the disk utilization looks:

Actual data (apparent-size):

Compressed data:

Compression ratio:

(Looks like the compression ratio reported is not 100% correct, we expect ~10x compression ratio.)

Too many tiny files

This is usually the big issue with databases that create a file per table. With MySQL 8.0 we can create a shared tablespace and “assign” a table to it. I created a tablespace per database, and created 1000 tables in each database.

The result:

Creating tables

Another big challenge is how to create tables fast enough so it will not take months. I have used three approaches:

  1. Disabled all possible consistency checks in MySQL, and decreased the innodb page size to 4K (these config options are NOT for production use)
  2. Created tables in parallel: as the mutex contention bug in MySQL 8.0 has been fixed, creating tables in parallel works fine.
  3. Use local NVMe cards on top of an AWS ec2 i3.8xlarge instance

my.cnf config file (I repeat: do not use this in production):

ZFS pool:

A simple “deploy” script to create tables in parallel (includes the sysbench table structure):

How fast did we create tables? Here are some stats:

So we created ~650 tables per second. The average, above, is per 10 seconds.

Counting the tables

It took > 6 hours to do “count(*) from information_schema.tables”! Here is why:

  1. MySQL 8.0 uses a new data dictionary (this is great as it avoids creating 1 billion frm files). Everything is stored in this file:
  2. The information_schema.tables is actually a view:

and the explain plan looks like this:

Conclusions

  1. I have created more than 1 billion real InnoDB tables with indexes in MySQL 8.0, just for fun, and it worked. It took ~2 weeks to create.
  2. Probably MySQL 8.0 is the first version where it is even practically possible to create billion InnoDB tables
  3. ZFS compression together with NVMe cards makes it reasonably cheap to do, for example, by using i3.4xlarge or i3.8xlarge instances on AWS.

one billion tables MySQL

9 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Matt

Loved this post. Now what to do with those 1 billion empty tables?

McFlew van Landed on ya feet

What a great lab/test/mythbuster case thanks for sharing all the specs and steps involved!

just rm -rf /var/lib/mysql/ that’s what you do with 1bi empty tables and then you reinstall mysql from scratch.

Heidi Schmidt

What OS did you use ZFS with and what was the default settings for io capacity with respect to EBS SSD? (If you wouldn’t mind posting the show global variables — it would be interesting to see.) Thanks!

Diego

Next challenge: what about MariaDB 10? 😉

Diego

I think MariaDB 10.x is not based on MySQL 5.x but it’s a new development (and not compatible with MySQL 5.x), but I don’t now if it still uses one FRM file per table.

dobo

“MariaDB 10.0 is a stable (GA) release of MariaDB. It is built on the MariaDB 5.5 series with backported features from MySQL 5.6 and entirely new features not found anywhere else.” (from mariadb.org)