Finding the largest tables on a MySQL instance is a no brainer in MySQL 5.0+ thanks to Information Schema, but I still wanted to post a little query I use for the purpose so I can easily find it later. Plus it is quite handy in a way it presents information:

SELECT CONCAT(table_schema, '.', table_name), CONCAT(ROUND(table_rows / 1000000, 2), 'M') rows, CONCAT(ROUND(data_length / ( 1024 * 1024 * 1024 ), 2), 'G') DATA, CONCAT(ROUND(index_length / ( 1024 * 1024 * 1024 ), 2), 'G') idx, CONCAT(ROUND(( data_length + index_length ) / ( 1024 * 1024 * 1024 ), 2), 'G') total_size, ROUND(index_length / data_length, 2) idxfrac FROM information_schema.TABLES ORDER BY data_length + index_length DESC LIMIT 10; +-------------------------------------+--------+--------+--------+------------+---------+ | concat(table_schema,'.',table_name) | rows | data | idx | total_size | idxfrac | +-------------------------------------+--------+--------+--------+------------+---------+ | art87.link_out87 | 37.25M | 14.83G | 14.17G | 29.00G | 0.96 | | art87.article87 | 12.67M | 15.83G | 4.79G | 20.62G | 0.30 | | art116.article116 | 10.49M | 12.52G | 3.65G | 16.18G | 0.29 | | art84.article84 | 10.10M | 10.11G | 3.59G | 13.70G | 0.35 | | art104.link_out104 | 23.66M | 6.63G | 6.55G | 13.18G | 0.99 | | art118.article118 | 7.06M | 10.49G | 2.68G | 13.17G | 0.26 | | art106.article106 | 9.86M | 10.19G | 2.76G | 12.95G | 0.27 | | art85.article85 | 6.20M | 9.82G | 2.51G | 12.33G | 0.26 | | art91.article91 | 8.66M | 9.17G | 2.66G | 11.83G | 0.29 | | art94.article94 | 5.21M | 10.10G | 1.69G | 11.79G | 0.17 | +-------------------------------------+--------+--------+--------+------------+---------+ 10 rows in set (2 min 29.19 sec) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 SELECT CONCAT ( table_schema , '.' , table_name ) , CONCAT ( ROUND ( table_rows / 1000000 , 2 ) , 'M' ) rows , CONCAT ( ROUND ( data_length / ( 1024 * 1024 * 1024 ) , 2 ) , 'G' ) DATA , CONCAT ( ROUND ( index_length / ( 1024 * 1024 * 1024 ) , 2 ) , 'G' ) idx , CONCAT ( ROUND ( ( data_length + index _ length ) / ( 1024 * 1024 * 1024 ) , 2 ) , 'G' ) total_size , ROUND ( index_length / data_length , 2 ) idxfrac FROM information_schema .TABLES ORDER BY data_length + index_length DESC LIMIT 10 ; + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- + -- -- -- -- + -- -- -- -- + -- -- -- -- -- -- + -- -- -- -- - + | concat ( table_schema , '.' , table_name ) | rows | data | idx | total_size | idxfrac | + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- + -- -- -- -- + -- -- -- -- + -- -- -- -- -- -- + -- -- -- -- - + | art87 .link_out87 | 37.25M | 14.83G | 14.17G | 29.00G | 0.96 | | art87 .article87 | 12.67M | 15.83G | 4.79G | 20.62G | 0.30 | | art116 .article116 | 10.49M | 12.52G | 3.65G | 16.18G | 0.29 | | art84 .article84 | 10.10M | 10.11G | 3.59G | 13.70G | 0.35 | | art104 .link_out104 | 23.66M | 6.63G | 6.55G | 13.18G | 0.99 | | art118 .article118 | 7.06M | 10.49G | 2.68G | 13.17G | 0.26 | | art106 .article106 | 9.86M | 10.19G | 2.76G | 12.95G | 0.27 | | art85 .article85 | 6.20M | 9.82G | 2.51G | 12.33G | 0.26 | | art91 .article91 | 8.66M | 9.17G | 2.66G | 11.83G | 0.29 | | art94 .article94 | 5.21M | 10.10G | 1.69G | 11.79G | 0.17 | + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- + -- -- -- -- + -- -- -- -- + -- -- -- -- -- -- + -- -- -- -- - + 10 rows in set ( 2 min 29.19 sec )

I do some converting and rounding to see number of rows in millions and data and index size in GB so I can save on counting zeros.

The last column shows how much the index takes compared to the data which is mainly for informational purposes, but for MyISAM can also help you to size your key buffer compared to operating system cache.

I also use it to see which tables may be worth to review in terms of indexes. Large index size compared to data size often indicates there is a lot of indexes (so it is well possible there are some duplicates, redundant or simply unused indexes among them) or maybe there is a long primary key with Innodb tables. Of course, it also could be a perfectly fine table, but it is worth to look.

Changing the query a bit you can look for different sorting order or extra data, such as average row length, you can learn quite a lot about your schema this way.

It is also worth to note queries on information_schema can be rather slow if you have a lot of large tables. On this instance, it took 2.5 minutes to run for 450 tables.

UPDATE: To make things easier I’ve added INFORMATION_SCHEMA to the query so it works whatever database you have active. It does not work with MySQL before 5.0 still, of course 🙂