Checking table size in MySQL or MariaDB helps prioritize cleanup, capacity planning, and performance tuning by revealing which objects consume the most storage. Large tables and indexes can quietly dominate disk usage, backups, and restore times, even when the application footprint looks small.
Table size is exposed through metadata in INFORMATION_SCHEMA, especially INFORMATION_SCHEMA.TABLES. The columns data_length and index_length represent the estimated on-disk bytes used by table data and indexes, and combining them provides a practical “total table size” for ranking and reporting.
Values depend on the storage engine and statistics freshness. InnoDB row counts (table_rows) are often estimates, and size numbers can reflect allocated space rather than only used space; data_free can indicate reclaimable space but is not a guarantee. On very large tables, refreshing statistics can add load, and installations using a shared InnoDB system tablespace can make “per-table file size” differ from “allocated bytes attributed to a table.”
Steps to check table size:
- Open a MySQL or MariaDB client session.
$ mysql --user=root --password Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. ##### snipped ##### mysql>
On some systems, the client binary is named mariadb; the SQL steps remain the same.
- Select the target database (schema).
mysql> USE myapp; Database changed
Replace myapp with the schema name that contains the table.
- Show size and related metadata for a single table.
mysql> SELECT table_schema, table_name, engine, table_rows, 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, ROUND(data_free / 1024 / 1024, 2) AS free_mb FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'orders'; +--------------+------------+--------+-----------+---------+----------+----------+---------+ | table_schema | table_name | engine | table_rows | data_mb | index_mb | total_mb | free_mb | +--------------+------------+--------+-----------+---------+----------+----------+---------+ | myapp | orders | InnoDB | 182345 | 256.00 | 64.00 | 320.00 | 0.00 | +--------------+------------+--------+-----------+---------+----------+----------+---------+ 1 row in set (0.00 sec)Replace orders with the table name; table_rows can be approximate for InnoDB, and free_mb is derived from data_free.
- List table sizes in the selected schema sorted by total size.
mysql> SELECT table_name, engine, table_rows, ROUND((data_length + index_length) / 1024 / 1024, 2) AS total_mb FROM information_schema.tables WHERE table_schema = DATABASE() ORDER BY (data_length + index_length) DESC; +----------------+--------+-----------+----------+ | table_name | engine | table_rows | total_mb | +----------------+--------+-----------+----------+ | orders | InnoDB | 182345 | 320.00 | | order_items | InnoDB | 1023345 | 210.50 | | customers | InnoDB | 25000 | 45.20 | ##### snipped ##### +----------------+--------+-----------+----------+ 45 rows in set (0.01 sec) - Calculate the total size of the selected schema by summing table sizes.
mysql> SELECT table_schema AS schema_name, ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS total_mb FROM information_schema.tables WHERE table_schema = DATABASE() GROUP BY table_schema; +------------+----------+ | schema_name | total_mb | +------------+----------+ | myapp | 1024.75 | +------------+----------+ 1 row in set (0.00 sec) - Identify the largest tables across non-system schemas.
mysql> SELECT table_schema, table_name, engine, ROUND((data_length + index_length) / 1024 / 1024, 2) AS total_mb FROM information_schema.tables WHERE table_schema NOT IN ('mysql', 'information_schema', 'performance_schema', 'sys') ORDER BY (data_length + index_length) DESC LIMIT 20; +------------+----------+--------+----------+ | table_schema | table_name | engine | total_mb | +------------+----------+--------+----------+ | analytics | events | InnoDB | 5120.75 | | myapp | orders | InnoDB | 320.00 | ##### snipped ##### +------------+----------+--------+----------+ 20 rows in set (0.02 sec) - Refresh statistics for a table when sizes or row counts look stale.
mysql> ANALYZE TABLE orders; +-------------+---------+----------+----------+ | Table | Op | Msg_type | Msg_text | +-------------+---------+----------+----------+ | myapp.orders | analyze | status | OK | +-------------+---------+----------+----------+ 1 row in set (0.12 sec)
ANALYZE TABLE can add load on large tables and busy servers; schedule it for low-traffic windows when possible.
- Confirm the reported byte counts with SHOW TABLE STATUS.
mysql> SHOW TABLE STATUS LIKE 'orders'\G *************************** 1. row *************************** Name: orders Engine: InnoDB Rows: 182345 Data_length: 268435456 Index_length: 67108864 Data_free: 0 Create_time: 2024-01-02 11:22:33 Update_time: NULL ##### snipped #####Data_length and Index_length are bytes; compare them to the INFORMATION_SCHEMA query for consistency.
- Exit the client session.
mysql> EXIT Bye
Mohd Shakir Zakaria is a cloud architect with deep roots in software development and open-source advocacy. Certified in AWS, Red Hat, VMware, ITIL, and Linux, he specializes in designing and managing robust cloud and on-premises infrastructures.
Comment anonymously. Login not required.
