0

Having a production database that is growing I started to make some tests (on a copy) in order to decide whit ROW_FORMAT should be better. The tables where created without specifying a format so no surprise when I found them stored in Dynamic format. Here is a line from show table status; command output:

+--------------------+--------+---------+------------+--------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+------------+-----------------+----------+--------------------+---------+
| Name               | Engine | Version | Row_format | Rows   | Avg_row_length | Data_length | Max_data_length | Index_length | Data_free | Auto_increment | Create_time         | Update_time         | Check_time | Collation       | Checksum | Create_options     | Comment |
+--------------------+--------+---------+------------+--------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+------------+-----------------+----------+--------------------+---------+

| DOM_INTEGRATION    | InnoDB |      10 | Dynamic    |  33460 |        110 |     3686400 |               0 |     11059200 |   4194304 |       NULL | 2022-01-10 13:27:26 | NULL                | NULL       | utf8_general_ci |     NULL |

where 11059200 is the index length. Now simply typing:

mysql> ALTER TABLE DOM_INTEGRATION ROW_FORMAT=Dynamic;
Query OK, 0 rows affected (3.98 sec)
Records: 0  Duplicates: 0  Warnings: 0

Produce a sharp change in the index length:

| DOM_INTEGRATION    | InnoDB |      10 | Dynamic    |  32619 |            113 |     3686400 |               0 |      5816320 |   2097152 |           NULL | 2022-01-10 14:37:05 | NULL                | NULL       | utf8_general_ci |     NULL | row_format=DYNAMIC |         |

that is now reduced to 5816320 . What happened ? also the number of rows seems different? Setting a row format to Dynamic as it was I was expecting no change. This is the table structure and it's indices:

+------------+--------------+------+-----+---------+-----------------------------+
| Field      | Type         | Null | Key | Default | Extra                       |
+------------+--------------+------+-----+---------+-----------------------------+
| DOMUPI     | varchar(300) | NO   | PRI | NULL    |                             |
| POS        | varchar(255) | NO   | PRI | NULL    |                             |
| PRODUPI    | varchar(300) | YES  | MUL | NULL    |                             |
| B_id       | int          | YES  | MUL | NULL    |                             |
| Modifiable | tinyint(1)   | NO   |     | 1       |                             |
| NPOS       | int          | YES  |     | NULL    | VIRTUAL GENERATED           |
| OpTime     | timestamp    | YES  |     | NULL    | on update CURRENT_TIMESTAMP |
+------------+--------------+------+-----+---------+-----------------------------+

+-----------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table           | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+-----------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| DOM_INTEGRATION |          0 | PRIMARY  |            1 | DOMUPI      | A         |         649 |     NULL |   NULL |      | BTREE      |         |               | YES     | NULL       |
| DOM_INTEGRATION |          0 | PRIMARY  |            2 | POS         | A         |       32619 |     NULL |   NULL |      | BTREE      |         |               | YES     | NULL       |
| DOM_INTEGRATION |          1 | POS      |            1 | POS         | A         |         277 |     NULL |   NULL |      | BTREE      |         |               | YES     | NULL       |
| DOM_INTEGRATION |          1 | B_id     |            1 | B_id        | A         |         192 |     NULL |   NULL | YES  | BTREE      |         |               | YES     | NULL       |
| DOM_INTEGRATION |          1 | IDX_DMP  |            1 | PRODUPI     | A         |       18110 |     NULL |   NULL | YES  | BTREE      |         |               | YES     | NULL       |
+-----------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+

What I'm doing wrong?

Shadow
  • 33,525
  • 10
  • 51
  • 64
GBBL
  • 576
  • 1
  • 6
  • 18
  • The ALTER TABLE rewrote the tablespace, and as a side effect, it stored the index more compactly. Over time as you insert, update, and delete rows, the index will become defragmented. Unfortunately there is no way to get a report of how much of the space is wasted by defragmentation. You can only try to use `OPTIMIZE TABLE ` or `ALTER TABLE FORCE` once in a while to see if you can recover some space. Any other `ALTER TABLE` that changes the storage format will do the same thing. – Bill Karwin Jan 10 '22 at 16:15
  • Thank you very much ! Very interesting. If you post this as an answer I will vote it! – GBBL Jan 11 '22 at 09:44
  • Some Tests: Starting from: DOM_INTEGRATION | InnoDB | 10 | Dynamic | 33448 | 110 | 3686400 | 0 | 10010624 | 4194304 | simply an analyze table DOM_INTEGRATION; has a result | DOM_INTEGRATION | InnoDB | 10 | Dynamic | 32597 | 113 | 3686400 | 0 | 10010624 | 4194304 | So some rows where removed. After an ALTER TABLE DOM_INTEGRATION force; and analyse | DOM_INTEGRATION | InnoDB | 10 | Dynamic | 33235 | 110 | 3686400 | 0 | 6864896 | 2097152 | – GBBL Jan 11 '22 at 10:44
  • Each time you run ANALYZE TABLE it takes a new sampling of the table, and estimates the number of rows from that. So it is common for the numbers in the SHOW TABLE STATUS report to change, even if the actual rows in the table have not changed. – Bill Karwin Jan 11 '22 at 15:02
  • I can't post an answer since @Shadow has closed it. – Bill Karwin Jan 11 '22 at 15:02
  • I voted to reopen it I have read the other interesting question and found it quite different. In fact I your answer is quite interesting and I'm planning to introduce a CRON task to make a alter table force to all tables of database once every week. For some tables i have found that the size increased after the operation but not much. With just that shrink the db about 20% without any real modification. – GBBL Jan 12 '22 at 13:49

0 Answers0