05.08.2019

MySQL-таблица занимает много места на диске, при малом количество данных в самой таблице

Кейс: в таблице (InnoDB) 39 записей на 65KB, а места на диске таблица занимает 2,6G:

user@site:~# du -sh /var/lib/mysql/site/* | grep b_composite_page
16K     /var/lib/mysql/site/b_composite_page.frm
2,6G    /var/lib/mysql/site/b_composite_page.ibd

Почему так? Как почистить место? Результат команды SHOW TABLE таблицы:

MariaDB [site]> SHOW TABLE STATUS LIKE 'b_composite_page'\G;
*************************** 1. row ***************************
           Name: b_composite_page
         Engine: InnoDB
        Version: 10
     Row_format: Compact
           Rows: 39
 Avg_row_length: 420
    Data_length: 16384
Max_data_length: 0
   Index_length: 49152
      Data_free: 2648702976
 Auto_increment: 132230
    Create_time: 2018-02-11 00:49:29
    Update_time: NULL
     Check_time: NULL
      Collation: utf8_unicode_ci
       Checksum: NULL
 Create_options:
        Comment:
1 row in set (0.01 sec)

ERROR: No query specified    

Видим, что Data_free (количество выделенных, но неиспользуемых байтов) заоблачный. При том, что Data_length + Index_length крохотный.

При вставке в InnoDB-таблицы место на диске увеличивается, а при удалении не уменьшается.

Лечится это ребилдом таблицы:

MariaDB [site]> ALTER TABLE b_composite_page Engine=InnoDB;
Query OK, 0 rows affected (0.11 sec)
Records: 0  Duplicates: 0  Warnings: 0    

При желании можно ещё запустить оптимизацию:

MariaDB [site]> OPTIMIZE TABLE b_composite_page;
+-----------------------+----------+----------+-------------------------------------------------------------------+
| Table                 | Op       | Msg_type | Msg_text                                                          |
+-----------------------+----------+----------+-------------------------------------------------------------------+
| site.b_composite_page | optimize | note     | Table does not support optimize, doing recreate + analyze instead |
| site.b_composite_page | optimize | status   | OK                                                                |
+-----------------------+----------+----------+-------------------------------------------------------------------+
2 rows in set (0.10 sec)    

В итоге видим, что теперь всё стало больше похоже на правду:

MariaDB [site]> SHOW TABLE STATUS LIKE 'b_composite_page'\G;
*************************** 1. row ***************************
           Name: b_composite_page
         Engine: InnoDB
        Version: 10
     Row_format: Compact
           Rows: 40
 Avg_row_length: 409
    Data_length: 16384
Max_data_length: 0
   Index_length: 49152
      Data_free: 0
 Auto_increment: 132231
    Create_time: 2018-07-19 01:08:02
    Update_time: NULL
     Check_time: NULL
      Collation: utf8_unicode_ci
       Checksum: NULL
 Create_options:
        Comment:
1 row in set (0.00 sec)

ERROR: No query specified    
Оригинал статьи