Tracking database size prevents unexpected disk exhaustion and helps plan storage for backups, replicas, and schema changes. Size checks are also useful for pinpointing which schema or table is driving growth when maintenance windows start to stretch.

MySQL and MariaDB expose storage metadata through information_schema, which contains per-table statistics such as data_length and index_length. Summing these values across information_schema.TABLES provides per-schema totals and highlights the largest tables without filesystem access.

Reported sizes are approximate for some engines (especially InnoDB) and may reflect allocated pages rather than exact on-disk bytes. Results can be incomplete without privileges on the underlying objects, and the totals exclude non-table disk usage such as binary logs, redo logs, and temporary files, so filesystem usage of the data directory can be higher.

Steps to check MySQL or MariaDB database size:

  1. Open a mysql client session on the target server.
    $ mysql --user=root --password
    Enter password:
    Welcome to the MySQL monitor.  Commands end with ; or \g.
    Server version: 8.0.36 MySQL Community Server - GPL
    
    mysql>
  2. List schema sizes using information_schema.TABLES.
    mysql> SELECT
        ->   table_schema AS `Database`,
        ->   ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS `Size (MiB)`
        -> FROM information_schema.TABLES
        -> GROUP BY table_schema
        -> ORDER BY SUM(data_length + index_length) DESC;
    +--------------------+------------+
    | Database           | Size (MiB) |
    +--------------------+------------+
    | appdb              |    1520.44 |
    | analytics          |     987.12 |
    | mysql              |      23.56 |
    | performance_schema |       0.00 |
    | information_schema |       0.00 |
    +--------------------+------------+
    5 rows in set (0.02 sec)

    Replace / 1024 / 1024 with / 1024 / 1024 / 1024 to display GiB.

  3. Exclude system schemas when reviewing application growth.
    mysql> SELECT
        ->   table_schema AS `Database`,
        ->   ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS `Size (MiB)`
        -> FROM information_schema.TABLES
        -> WHERE table_schema NOT IN ('information_schema','mysql','performance_schema','sys')
        -> GROUP BY table_schema
        -> ORDER BY SUM(data_length + index_length) DESC;
    +-----------+------------+
    | Database  | Size (MiB) |
    +-----------+------------+
    | appdb     |    1520.44 |
    | analytics |     987.12 |
    +-----------+------------+
    2 rows in set (0.01 sec)
  4. Show the total size for a single schema.
    mysql> SELECT
        ->   table_schema AS `Database`,
        ->   ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS `Size (MiB)`
        -> FROM information_schema.TABLES
        -> WHERE table_schema = 'appdb'
        -> GROUP BY table_schema;
    +----------+------------+
    | Database | Size (MiB) |
    +----------+------------+
    | appdb    |    1520.44 |
    +----------+------------+
    1 row in set (0.01 sec)

    Replace appdb with the schema name from SHOW DATABASES.

  5. List the largest tables in a schema by total size.
    mysql> SELECT
        ->   table_name AS `Table`,
        ->   engine AS `Engine`,
        ->   ROUND((data_length + index_length) / 1024 / 1024, 2) AS `Size (MiB)`,
        ->   table_rows AS `Rows (est.)`
        -> FROM information_schema.TABLES
        -> WHERE table_schema = 'appdb'
        -> ORDER BY (data_length + index_length) DESC
        -> LIMIT 10;
    +-----------+--------+------------+-------------+
    | Table     | Engine | Size (MiB) | Rows (est.) |
    +-----------+--------+------------+-------------+
    | events    | InnoDB |     612.73 |    34122120 |
    | users     | InnoDB |     210.11 |     2184421 |
    | audit_log | InnoDB |     198.07 |    11233455 |
    ##### snipped #####
    10 rows in set (0.03 sec)

    table_rows is an estimate for InnoDB and can be inaccurate without fresh statistics.

  6. Split table size into data, index, and free space for closer inspection.
    mysql> SELECT
        ->   table_name AS `Table`,
        ->   ROUND(data_length / 1024 / 1024, 2) AS `Data (MiB)`,
        ->   ROUND(index_length / 1024 / 1024, 2) AS `Index (MiB)`,
        ->   ROUND(data_free / 1024 / 1024, 2) AS `Free (MiB)`,
        ->   ROUND((data_length + index_length) / 1024 / 1024, 2) AS `Total (MiB)`
        -> FROM information_schema.TABLES
        -> WHERE table_schema = 'appdb'
        -> ORDER BY (data_length + index_length) DESC
        -> LIMIT 10;
    +-----------+------------+-------------+-----------+------------+
    | Table     | Data (MiB) | Index (MiB) | Free (MiB)| Total (MiB)|
    +-----------+------------+-------------+-----------+------------+
    | events    |     464.51 |      148.22 |     12.00 |     612.73 |
    | users     |     173.61 |       36.50 |      0.00 |     210.11 |
    ##### snipped #####
    10 rows in set (0.03 sec)

    data_free can represent reclaimable space depending on engine and tablespace layout.

  7. Refresh table statistics when sizes appear stale.
    mysql> ANALYZE TABLE appdb.events;
    +-------------+---------+----------+----------+
    | Table       | Op      | Msg_type | Msg_text |
    +-------------+---------+----------+----------+
    | appdb.events| analyze | status   | OK       |
    +-------------+---------+----------+----------+
    1 row in set (1.21 sec)

    ANALYZE TABLE can increase I/O and CPU usage on busy servers.

  8. Show the server data directory when correlating SQL totals with disk usage.
    mysql> SELECT @@datadir AS `Data directory`;
    +----------------+
    | Data directory |
    +----------------+
    | /var/lib/mysql/|
    +----------------+
    1 row in set (0.00 sec)

    Directory contents often include logs and engine files not reflected in information_schema totals.

  9. Exit the mysql client session.
    mysql> \q
    $
Discuss the article:

Comment anonymously. Login not required.