Back to Blog
How To 10 min read

TL;DR - Query information_schema.TABLES to check MySQL database size in one command: SELECT table_schema, ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS size_mb FROM information_schema.TABLES GROUP BY table_schema; - For per-table breakdown, query the same view filtered by your database name to see each table's data size, index size, and row count. - In phpMyAdmin, the database overview page shows size per table automatically — no SQL needed. - Watch out for ibdata1: if innodb_file_per_table is OFF, information_schema may underreport actual disk usage by 30-60%. - Tables with high fragmentation can be reclaimed with OPTIMIZE TABLE — this is the fastest way to recover wasted space.

Table of Contents


How to Check Your MySQL Database Size (GUI and SQL Methods)

Your disk usage alert just fired, your managed database is creeping toward its plan limit, or you simply need to know which table is eating all the space. Whatever brought you here, knowing how to check MySQL database size is a routine task that every developer and DBA runs into. The good news: MySQL exposes all the size metadata you need through information_schema, and the queries are short.

This guide covers four methods — from a single SQL query for total size, to per-table breakdowns, data vs. index analysis, and the phpMyAdmin GUI approach. We also cover the most common gotcha that makes size reporting inaccurate (ibdata1) and practical ways to reclaim wasted space.


Method 1: Total Database Size with SQL

The fastest way to check MySQL database size is a single query against information_schema.TABLES. This system view contains metadata about every table in every database on the server, including data_length (bytes used by row data) and index_length (bytes used by indexes).

Size of a single database

SELECT
  table_schema AS database_name,
  ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS size_mb
FROM information_schema.TABLES
WHERE table_schema = 'your_database_name'
GROUP BY table_schema;

Replace your_database_name with your actual database name. The result looks like this:

+----------------+---------+
| database_name  | size_mb |
+----------------+---------+
| my_app         |  487.23 |
+----------------+---------+

Size of all databases on the server

SELECT
  table_schema AS database_name,
  ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS size_mb
FROM information_schema.TABLES
GROUP BY table_schema
ORDER BY size_mb DESC;

This returns every database including system databases (mysql, information_schema, performance_schema, sys). Filter them out with WHERE table_schema NOT IN ('mysql', 'information_schema', 'performance_schema', 'sys') if you only want user databases.

A note on units: data_length and index_length are in bytes. Dividing by 1024 twice gives mebibytes (MiB), which is what most tools and hosting providers report. If your provider uses gigabytes, divide by 1024 a third time. For context, AWS RDS provisions storage in gibibytes, DigitalOcean Managed Databases report in GB, and most shared hosting panels display MB.


Method 2: Per-Table Size Breakdown

Total database size tells you whether you have a problem. Per-table size tells you where the problem is. In most production databases, 2-3 tables account for 80% or more of total size.

SELECT
  table_name,
  ROUND(data_length / 1024 / 1024, 2) AS data_mb,
  ROUND(index_length / 1024 / 1024, 2) AS index_mb,
  ROUND((data_length + index_length) / 1024 / 1024, 2) AS total_mb,
  table_rows
FROM information_schema.TABLES
WHERE table_schema = 'your_database_name'
ORDER BY total_mb DESC;

Example output:

+------------------+---------+----------+----------+------------+
| table_name       | data_mb | index_mb | total_mb | table_rows |
+------------------+---------+----------+----------+------------+
| audit_logs       |  312.45 |    87.12 |   399.57 |    4281930 |
| user_events      |   52.18 |    21.44 |    73.62 |     891204 |
| sessions         |    8.92 |     2.11 |    11.03 |      43892 |
| users            |    1.84 |     0.72 |     2.56 |      12841 |
| settings         |    0.05 |     0.02 |     0.07 |        347 |
+------------------+---------+----------+----------+------------+

Important: the table_rows column is an estimate for InnoDB tables, not an exact count. MySQL's InnoDB storage engine uses statistical sampling, so the row count can be off by 10-40% on large tables. If you need an exact count, run SELECT COUNT(*) FROM table_name — but be aware that on tables with millions of rows, this query can take seconds to minutes because InnoDB must do a full index scan.


Method 3: Data Size vs Index Size

When a database is larger than expected, the cause is usually one of two things: too much data, or oversized indexes. Separating the two helps you decide whether to archive old rows or drop unused indexes.

Database-level data vs index split

SELECT
  table_schema AS database_name,
  ROUND(SUM(data_length) / 1024 / 1024, 2) AS data_mb,
  ROUND(SUM(index_length) / 1024 / 1024, 2) AS index_mb,
  ROUND(SUM(index_length) / SUM(data_length) * 100, 1) AS index_to_data_pct
FROM information_schema.TABLES
WHERE table_schema = 'your_database_name'
GROUP BY table_schema;

The index_to_data_pct column tells you how much of your storage is indexes relative to data. As a rough benchmark:

  • 10-30% is typical for most transactional databases
  • 50%+ suggests you have many composite indexes or redundant indexes
  • 100%+ means your indexes are larger than your data — common on tables with lots of small rows and many indexed columns

According to Percona's research on MySQL index usage, up to 30% of indexes in production MySQL databases go completely unused. Dropping them is free disk space.

Find tables with the largest indexes

SELECT
  table_name,
  ROUND(index_length / 1024 / 1024, 2) AS index_mb,
  ROUND(index_length / (data_length + 1) * 100, 1) AS index_to_data_pct
FROM information_schema.TABLES
WHERE table_schema = 'your_database_name'
  AND data_length > 0
ORDER BY index_length DESC
LIMIT 10;

If a table shows an index-to-data ratio above 80%, check which indexes are actually used with the sys.schema_unused_indexes view (available in MySQL 5.7+):

SELECT * FROM sys.schema_unused_indexes
WHERE object_schema = 'your_database_name';

Method 4: Check Size in phpMyAdmin

If you prefer a visual approach, phpMyAdmin displays mysql table size information without writing any SQL.

Database overview

  1. Log in to phpMyAdmin and select your database from the left sidebar.
  2. The main panel shows a table list with columns for Rows, Type, Size, and Overhead.
  3. The Size column is the combined data + index size for each table.
  4. At the bottom of the table list, phpMyAdmin shows the total size for the entire database.

This is the fastest way to get a per-table size breakdown without remembering any queries.

Server-level overview

  1. From the phpMyAdmin home screen (click the server icon or the phpMyAdmin logo), select the Databases tab.
  2. You will see every database on the server with its total size listed in a Size column.
  3. Click any column header to sort — useful for finding the largest database quickly.

Checking overhead and fragmentation

In the table list, the Overhead column shows wasted space from fragmented tables. If a table shows significant overhead (e.g., 50 MB overhead on a 200 MB table), select it and use Maintenance > Optimize Table to reclaim the space.

If you do not have phpMyAdmin installed on your server, DBEverywhere gives you browser-based phpMyAdmin access to any remote MySQL database — just enter your credentials and connect. No installation, no Docker setup. The free tier includes 5 sessions per month.


The ibdata1 Gotcha (and innodb_file_per_table)

This is the most common reason developers see a mismatch between what information_schema reports and what their actual mysql disk usage looks like.

The problem

Before MySQL 5.6.6, the default behavior was to store all InnoDB data in a single shared file called ibdata1 (the InnoDB system tablespace). When you deleted rows or dropped tables, the space inside ibdata1 was marked as free but never returned to the operating system. The file only grew; it never shrank.

If your MySQL server was set up before 2013, or if you are on an older shared hosting provider, there is a good chance innodb_file_per_table is still OFF and your ibdata1 file is significantly larger than the sum of all table sizes reported by information_schema.

Check your setting

SHOW VARIABLES LIKE 'innodb_file_per_table';
  • ON (default since MySQL 5.6.6): each InnoDB table has its own .ibd file. information_schema sizes are accurate.
  • OFF: all InnoDB data lives in ibdata1. The data_length values in information_schema report logical size, not actual disk consumption.

Check actual disk usage

If you have SSH access:

# Check ibdata1 size
ls -lh /var/lib/mysql/ibdata1

# Check per-database directory sizes
du -sh /var/lib/mysql/*/

On managed databases (RDS, DigitalOcean, PlanetScale), you cannot access the filesystem directly. Use your provider's dashboard to see actual storage consumption and compare it to information_schema numbers. A 30-60% discrepancy between the two is common when ibdata1 has accumulated years of dead space.

The fix

If innodb_file_per_table is OFF:

  1. Set innodb_file_per_table = ON in your MySQL configuration.
  2. Run ALTER TABLE table_name ENGINE=InnoDB; for each table. This rebuilds the table into its own .ibd file.
  3. The space will not be reclaimed from ibdata1 itself — that file cannot shrink. To reclaim it, you must dump all data, stop MySQL, delete ibdata1 and redo logs, restart, and re-import. This is a significant operation best done during a maintenance window.

How to Reduce MySQL Database Size

Once you know where the space is going, here are the most effective ways to shrink your mysql database size.

1. Optimize fragmented tables

After heavy UPDATE or DELETE operations, InnoDB tables accumulate fragmented space. Reclaim it:

OPTIMIZE TABLE your_table_name;

For InnoDB, this is equivalent to ALTER TABLE ... ENGINE=InnoDB — it rebuilds the table and reclaims unused space. On a 10 GB table with 20% fragmentation, this can recover 2 GB. Note that OPTIMIZE TABLE locks the table for writes during the rebuild (MySQL 8.0 uses online DDL to minimize this, but expect some impact on large tables).

2. Drop unused indexes

Every index consumes disk space and slows down writes. Find and drop the ones nobody uses:

-- Find unused indexes (MySQL 5.7+)
SELECT * FROM sys.schema_unused_indexes
WHERE object_schema = 'your_database_name';

-- Drop an unused index
ALTER TABLE your_table DROP INDEX index_name;

3. Archive or purge old data

Log tables, audit trails, and event tables are the usual suspects. If your audit_logs table has 50 million rows and you only query the last 90 days, move older rows to a separate archive table or delete them:

-- Delete rows older than 90 days
DELETE FROM audit_logs WHERE created_at < NOW() - INTERVAL 90 DAY LIMIT 10000;

Use LIMIT to delete in batches and avoid locking the table for too long. Run the DELETE in a loop until zero rows are affected.

4. Compress InnoDB tables

InnoDB supports page-level compression that can reduce table size by 40-70%, depending on the data:

ALTER TABLE your_table ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8;

This works best on tables with text-heavy columns. It adds CPU overhead during reads and writes, so benchmark before applying to high-traffic tables.

5. Use appropriate data types

A common source of wasted space is oversized columns — storing UUIDs in VARCHAR(255) instead of CHAR(36), using BIGINT for a column that will never exceed 65,535 (SMALLINT saves 6 bytes per row), or storing booleans as INT instead of TINYINT(1). On a table with 10 million rows, switching a single column from BIGINT to INT saves 40 MB.


FAQ

How often should I check MySQL database size?

For production databases, check weekly or set up monitoring through your hosting provider's dashboard. Most managed database providers (AWS RDS, DigitalOcean, PlanetScale) include storage alerts that notify you at 80% and 90% capacity. If you are self-hosting, add a cron job that logs the output of the information_schema total size query to catch unexpected growth before it fills your disk.

Does querying information_schema affect database performance?

No, querying information_schema.TABLES is lightweight. MySQL caches the table statistics, so the query reads metadata rather than scanning actual table data. On a server with thousands of tables, the query completes in under 100 milliseconds. The only exception is if innodb_stats_on_metadata is ON, which causes InnoDB to recalculate statistics on every metadata query — but this setting defaults to OFF since MySQL 5.6.

Why does information_schema show a different size than my disk usage?

Three common causes: (1) innodb_file_per_table is OFF and ibdata1 contains dead space from dropped tables or deleted rows. (2) Binary logs (binlog) are consuming disk space that is not reflected in information_schema. On active servers, binary logs can account for 20-50% of total MySQL disk usage. (3) InnoDB's undo logs and redo logs use additional space. Check disk usage with du -sh /var/lib/mysql/ for the complete picture.

Can I check database size without SQL access?

Yes. phpMyAdmin and Adminer both display table and database sizes in their web interfaces without writing any queries. If you do not have either tool installed, DBEverywhere provides browser-based phpMyAdmin and Adminer that connect to any remote MySQL database. Enter your credentials, connect, and the database overview page shows all sizes immediately.

What is a normal database size for a web application?

It varies widely, but here are rough benchmarks: a typical SaaS application with 10,000 users and a year of data runs between 1-10 GB. E-commerce stores with product catalogs and order history are often 5-50 GB. Applications that store media metadata, logs, or analytics data can reach 100 GB+ within months. The important thing is not the absolute size but whether your storage plan accommodates growth. If your database grows 500 MB per month, plan for at least 12 months of runway.


Conclusion

Checking MySQL database size takes a single query against information_schema.TABLES — total size, per-table breakdown, data vs. index split, it is all there. For a visual approach, phpMyAdmin's database overview page shows the same information without writing SQL. The key gotcha to remember is ibdata1: if your server predates MySQL 5.6.6 or has innodb_file_per_table set to OFF, the numbers from information_schema will underreport actual disk consumption.

Once you identify the large tables, reduce size by optimizing fragmented tables, dropping unused indexes, archiving old data, or enabling InnoDB compression. These four actions cover the vast majority of cases.

Need to quickly check the size of a remote database without installing anything? DBEverywhere gives you browser-based phpMyAdmin and Adminer access to any MySQL database — connect in seconds and see table sizes, run information_schema queries, and manage your data from any browser. Start free with 5 sessions per month.

Try DBEverywhere Free

Access your database from any browser. No installation, no Docker, no SSH tunnels.

Get Started