“How big is my database?” is a question you will ask when disk space runs low or before a backup. MySQL answers it with INFORMATION_SCHEMA.TABLES.
Let us create a table and fill it with a few thousand rows to have something to measure.
SET SESSION cte_max_recursion_depth = 10000;
CREATE TABLE logs (
id INT AUTO_INCREMENT PRIMARY KEY,
message VARCHAR(200) NOT NULL,
created_at DATETIME NOT NULL
);
INSERT INTO logs (message, created_at)
WITH RECURSIVE n AS (SELECT 1 AS i UNION ALL SELECT i + 1 FROM n WHERE i < 5000)
SELECT CONCAT('Event number ', i), '2026-01-01 00:00:00' + INTERVAL i MINUTE FROM n;
SELECT COUNT(*) AS rows_inserted FROM logs;
+---------------+
| rows_inserted |
+---------------+
| 5000 |
+---------------+
1 row in set
(The WITH RECURSIVE query is a recursive CTE. It generates the numbers 1 to 5000. MySQL stops a recursive query after 1000 steps by default, so the first line raises the limit for this session. You will learn it in the CTE chapter.)
Size of one database
SELECT table_schema AS db,
ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS size_mb
FROM information_schema.tables
WHERE table_schema = 'learn'
GROUP BY table_schema;
+-------+---------+
| db | size_mb |
+-------+---------+
| learn | 0.27 |
+-------+---------+
1 row in set
(The exact number differs from one server to the next, because it depends on page layout and statistics. That is why the output is not compared here.)
Size of each table
SELECT table_name,
table_rows AS approx_rows,
ROUND(data_length / 1024, 1) AS data_kb,
ROUND(index_length / 1024, 1) AS index_kb
FROM information_schema.tables
WHERE table_schema = 'learn'
ORDER BY data_length + index_length DESC;
+------------+-------------+---------+----------+
| table_name | approx_rows | data_kb | index_kb |
+------------+-------------+---------+----------+
| logs | 5000 | 272.0 | 0.0 |
+------------+-------------+---------+----------+
1 row in set
| Column | Meaning |
|---|---|
table_rows | An estimate for InnoDB, not an exact count. Use COUNT(*) for the exact value. |
data_length | Bytes for the data (for InnoDB, this includes the primary key’s clustered index) |
index_length | Bytes for secondary indexes |
data_free | Unused space inside the table file |
Caveats
- The numbers are approximations, taken from statistics. After a large change they may lag. Run
ANALYZE TABLE logs;to refresh them. information_schemavalues are cached (information_schema_stats_expiry, 24 hours by default in MySQL 8). RunANALYZE TABLEor set the variable to0for fresh numbers during a check.- The size on disk can be bigger than
data_length + index_length, because of free space, the redo log, the undo log and the binary logs. - Large text and
BLOBcolumns may be stored off-page and still count indata_length.
Why it matters
- Backups and restores take time proportional to size.
- A table that grows by gigabytes should have a retention plan: archive or delete old rows (DELETE).
- Index size is part of the cost of an index (Indexes).
Find the biggest tables first
ORDER BY data_length + index_length DESC LIMIT 10 shows the tables that dominate your disk use, which is usually only a few.