Eliminar y recuperar espacio de la tabla InnoDB


14

Tengo una tabla InnoDB de 700 GB en la que no escribo más datos (solo lectura). Me gustaría eliminar los datos más antiguos que contiene y recuperar ese espacio en disco (ya que me estoy quedando sin él). La parte de eliminar es bastante fácil, porque tengo un índice primario autoincluido, así que solo puedo iterar en trozos usándolo y eliminar las filas, pero eso no me devolverá el espacio. Supongo que lo OPTIMIZE TABLEhará, pero eso podría llevar una eternidad en una mesa de 700GB, entonces, ¿hay otra opción que estoy pasando por alto?

Editar por RolandoMySQLDBA

Suponiendo que su tabla es mydb.mytable, ejecute la siguiente consulta y publíquela aquí para que pueda determinar el espacio en disco necesario para la reducción de la tabla:

SELECT
    FORMAT(dat/POWER(1024,3),2) datsize,
    FORMAT(ndx/POWER(1024,3),2) ndxsize,
    FORMAT((dat+ndx)/POWER(1024,3),2) tblsize
FROM (SELECT data_length dat,index_length ndx
FROM information_schema.tables WHERE
table_schema='mydb' AND table_name='mytable') A;

También debemos ver la estructura de la tabla, si está permitido.

Editar por Noam

Este es el resultado de la consulta:

datsize ndxsize tblsize
682.51 47.57 730.08

Esta es la estructura de la tabla ( SHOW CREATE TABLE)

`CREATE TABLE `mybigtable` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `uid` int(11) NOT NULL,  
  `created_at` datetime NOT NULL,  
  `tid` bigint(20) NOT NULL,  
  `text` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, 
  `ft` tinyint(1) NOT NULL,  
  `irtsd` bigint(20) NOT NULL,  
  `irtuid` int(11) NOT NULL,  
  `rc` int(11) NOT NULL,  
  `r` tinyint(1) NOT NULL,  
  `e` text CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,  `timezone` varchar(5) NOT NULL,  PRIMARY KEY (`id`),  UNIQUE KEY `uid_tid` (`uid`,`tid`)) ENGINE=InnoDB AUTO_INCREMENT=2006963844 DEFAULT CHARSET=utf8`

¿Tiene otro volumen de disco para capturar solo los datos?
RolandoMySQLDBA

@RolandoMySQLDBA Tengo un disco duro externo que puedo montar. ¿Eso cuenta?
Noam

@RolandoMySQLDBA pero, por supuesto, me gustaría una opción para eliminar algo de espacio sin necesidad de tener otros 700 GB
Noam

@RolandoMySQLDBA ¿El tamaño de disco adicional causa algún problema de rendimiento?
Aris

@Aris podría depender del disco y su tiempo de búsqueda. En estos días, la mayoría de los discos funcionan mejor ahora, pero ¿de qué sirve desperdiciar los ciclos (incluso yendo realmente rápido) si tiene grandes espacios dispersos de espacio en disco en su mesa ???. Esto es especialmente cierto para InnoDB, que normalmente se fija en bloques de 16K. Con la fragmentación interna de bloques de 16K, es posible que desee desfragmentar la tabla usando ALTER TABLE ... ENGINE=InnoDB;(si tiene espacio para hacerlo). La mayoría está satisfecha con sus SSD muy rápidos y ya no se preocuparía.
RolandoMySQLDBA

Respuestas:


21

Esta es una buena pregunta. Tienes varias soluciones, pero tu mesa es bastante grande, así que ninguna será sin dolor :)

Tiene tres soluciones para "reducir" las tablas de InnoDB:

1. OPTIMIZAR LA TABLA

Puede usarlo OPTIMIZE TABLEcomo lo mencionó, pero debe preocuparse por la innodb_file_per_tablevariable:

mysql> show variables like "innodb_file_per_table";
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| innodb_file_per_table | ON    |
+-----------------------+-------+
1 row in set (0.00 sec)

Dejame explicar:

Con las OPTIMIZE TABLEtablas InnoDB, bloquea la tabla, copia los datos en una nueva tabla limpia (por eso se reduce el resultado), suelta la tabla original y cambia el nombre de la nueva tabla con el nombre original. Es por eso que debería preocuparse por tener el doble de la volumetría de su tabla disponible en su disco (durante la operación necesitará 2x700GB).

Cuando estás en innodb_file_per_table = ON. Todas las tablas tienen el archivo de datos adecuado. Por lo tanto, la OPTIMIZEdeclaración creará un nuevo archivo de datos (~ 700 GB) cuando finalice la operación, MySQL eliminará el original y cambiará el nombre del nuevo (por lo que al final los 700 GB, probablemente menos porque se reducirán) de datos generado durante la operación será lanzado)

Cuando estás en innodb_file_per_table = OFF. Todos los datos van a un archivo de datos: ibdata . Este archivo tiene una triste particularidad, no se puede reducir. Por lo tanto, durante el OPTIMIZEproceso, se creará su nueva tabla (cerca de 700 GB), pero incluso después de la operación de caída y cambio de nombre (y al final de la OPTIMIZEfase) su ibdata no liberará ~ 700 GB, por lo que quería liberar algunos datos pero tiene 700 GB más, genial ¿no?

2. CAMBIAR TABLA

También puede usar una ALTER TABLEdeclaración, la ALTER TABLEfuncionará de la misma manera que OPTIMIZE TABLE. Solo puedes usar:

ALTER TABLE myTable EGINE=InnoDB;

3. ALTERAR TABLA (EN LÍNEA)

El problema de OPTIMIZEy ALTER TABLEque bloquea la mesa durante la operación. Puede usar la herramienta Percona: pt-online-schema-change (desde Percona Toolkit: enlace ). pt-online-schema ... construirá un mecanismo con disparadores y una tabla temporal en la que permite que la tabla original esté disponible para leer y escribir durante la operación. Utilizo esta herramienta en producción porque ALTERes genial.

Tenga en cuenta que debería haber hecho FOREIGN KEYreferencia a su tabla, FK y desencadena el riesgo de producir un desastre. Para verificar estos requisitos previos, consulte:

mysql> SELECT COUNT(*) FROM information_schema.REFERENTIAL_CONSTRAINTS WHERE REFERENCED_TABLE_NAME = "myTable";
+----------+
| COUNT(*) |
+----------+
|        0 |
+----------+
1 row in set (0.04 sec)

Así es como uso pt-online-schema-change:

pt-online-schema-change --alter "ENGINE=InnoDB" D=myBase,t=myTable --user --ask-pass

Tenga en cuenta que mi nota sobre innodb_file_per_table también es cierta para esta solución.

4. mysqldump

La última solución es recrear todas las bases de datos de un volcado. Terriblemente largo, pero terriblemente eficiente. Tenga en cuenta que es la única solución para "reducir" el archivo ibdata.

Max.


¿También en la opción de alterar tabla en línea de la herramienta percona necesitaré 700 GB de espacio libre en disco?
Noam

Sí, pt-online solo usa algún mecanismo para hacer ALTER en línea, pero de todos modos hace un ALTER.
Maxime Fouilleul

@MaximeFouilleul ¿el tamaño de disco adicional causa algún problema de rendimiento?
Aris

1

Si tiene poco tamaño de disco, le sugiero que haga lo mismo que Max sugirió con pt-online-schema-change (ONLINE). He estado en la misma situación con una mesa mucho más pequeña (200 GB) y elegí hacer algo de compresión al mismo tiempo. Algo en este sentido debería funcionar:

pt-online-schema-change --alter="ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4" D=myBase,t=myTable --user --ask-pass

Esto solo funcionará si está en formato de barracuda y en formato COMPACTO de la tabla. También debe tener innodb_file_per_table habilitado. Esto puede hacer maravillas en el tamaño de su tabla, especialmente si hay mucho texto y si usa KEY_BLOCK_SIZE más pequeño, como 8K o incluso 4K (el valor predeterminado es 16K). También puede ver cuánto espacio puede ganar de múltiples puntos de referencia con respecto a este problema en otros blogs, pero la documentación de MySQL anuncia entre un 25% y un 50% (para mí era casi el 90%).

Tenga en cuenta que esto también puede afectar el rendimiento al hacer SELECT (de la documentación de MySQL):

Por lo tanto, en cualquier momento dado, el grupo de búferes puede contener las formas comprimidas y no comprimidas de la página, o solo la forma comprimida de la página, o ninguna.

MySQL también tiene que descomprimir los datos cuando no está en el grupo de búferes. Así que ten cuidado.

Esto realmente ha funcionado bien en mi caso. Tenía un mensaje largo. 200 GB se convirtieron en 26 GB. Las actuaciones no fueron alteradas.

Para obtener información más detallada, consulte estos enlaces:

https://dev.mysql.com/doc/refman/5.5/en/innodb-compression-usage.html

https://dev.mysql.com/doc/refman/5.5/en/innodb-compression-internals.html

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.