MySQL analytics: information_schema polling for table engine percentages

If you’ve ever needed to know how the data and index percentages per table engine were laid out on your MySQL server, but didn’t have the time to write out a query… here it is!

select 
(select (sum(DATA_LENGTH)+sum(INDEX_LENGTH))/(POW(1024,3)) as total_size from tables) as total_size_gb, 
(select sum(INDEX_LENGTH)/(POW(1024,3)) as index_size from tables) as total_index_gb, 
(select sum(DATA_LENGTH)/(POW(1024,3)) as data_size from tables) as total_data_gb, 

(select ((sum(INDEX_LENGTH) / ( sum(DATA_LENGTH) + sum(INDEX_LENGTH)))*100) as perc_index from tables) as perc_index,
(select ((sum(DATA_LENGTH) / ( sum(DATA_LENGTH) + sum(INDEX_LENGTH)))*100) as perc_data from tables) as perc_data,

(select ((sum(INDEX_LENGTH) / ( sum(DATA_LENGTH) + sum(INDEX_LENGTH)))*100) as perc_index from tables where ENGINE='innodb') as innodb_perc_index,
(select ((sum(DATA_LENGTH) / ( sum(DATA_LENGTH) + sum(INDEX_LENGTH)))*100) as perc_data from tables where ENGINE='innodb') as innodb_perc_data,

(select ((sum(INDEX_LENGTH) / ( sum(DATA_LENGTH) + sum(INDEX_LENGTH)))*100) as perc_index from tables where ENGINE='myisam') as myisam_perc_index,
(select ((sum(DATA_LENGTH) / ( sum(DATA_LENGTH) + sum(INDEX_LENGTH)))*100) as perc_data from tables where ENGINE='myisam') as myisam_perc_data,

(select (select sum(INDEX_LENGTH) from tables where ENGINE='innodb') / (select sum(INDEX_LENGTH) from tables))*100 as perc_total_index_innodb,
(select (select sum(DATA_LENGTH) from tables where ENGINE='innodb') / (select sum(DATA_LENGTH) from tables))*100 as perc_total_data_innodb,

(select (select sum(INDEX_LENGTH) from tables where ENGINE='myisam') / (select sum(INDEX_LENGTH) from tables))*100 as perc_total_index_myisam,
(select (select sum(DATA_LENGTH) from tables where ENGINE='myisam') / (select sum(DATA_LENGTH) from tables))*100 as perc_total_data_myisam

from tables limit 1\G

This will output something along the lines of:

          total_size_gb: 2.7505537783727
         total_index_gb: 0.018660545349121
          total_data_gb: 2.7318932330236
             perc_index: 0.6784
              perc_data: 99.3216
      innodb_perc_index: 0.6502
       innodb_perc_data: 99.3498
      myisam_perc_index: 17.5120
       myisam_perc_data: 82.4880
perc_total_index_innodb: 95.6713
 perc_total_data_innodb: 99.8607
perc_total_index_myisam: 4.3287
 perc_total_data_myisam: 0.1393

4 thoughts on “MySQL analytics: information_schema polling for table engine percentages

  1. Suresh Kuna says:

    Good one

  2. Hi!

    while I think the idea is nice, the query as you propose it does a lot of unnecessary work. Normally I am not big fan of premature optimization, but from experience I learned to avoid or at least be very careful with accessing MySQL’s information_schema tables multiple times in the same statement.

    For example, after repeatedly running your statement (excluding the first run) I find it takes about 2min44sec on average to run it. With a slight modification to access information_schema.tables only once:

    select (data_size + index_size) / gb as total_size
    , index_size / gb as index_size
    , data_size / gb as data_size
    , index_size / (data_size + index_size) * 100 as perc_index
    , data_size / (data_size + index_size) * 100 as perc_data
    , innodb_index_size / (innodb_data_size + innodb_index_size) * 100 as innodb_perc_index
    , innodb_data_size / (innodb_data_size + innodb_index_size) * 100 as innodb_perc_data
    , myisam_index_size / (myisam_data_size + myisam_index_size) * 100 as myisam_perc_index
    , myisam_data_size / (myisam_data_size + myisam_index_size) * 100 as myisam_perc_data
    , innodb_index_size / index_size * 100 as innodb_perc_total_index
    , innodb_data_size / data_size * 100 as innodb_perc_total_data
    , myisam_index_size / index_size * 100 as myisam_perc_total_index
    , myisam_data_size / data_size * 100 as myisam_perc_total_data
    from (
    select sum(data_length) data_size
    , sum(index_length) index_size
    , sum(if(engine = ‘innodb’, data_length, 0)) as innodb_data_size
    , sum(if(engine = ‘innodb’, index_length, 0)) as innodb_index_size
    , sum(if(engine = ‘myisam’, data_length, 0)) as myisam_data_size
    , sum(if(engine = ‘myisam’, index_length, 0)) as myisam_index_size
    , pow(1024, 3) gb
    from tables
    ) a

    I find an average execution time of slightly less than 10 seconds.

  3. admin says:

    Roland, thanks – that does run quicker!

  4. Eddi says:

    Brilliant one.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>