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 TABLE
hará, 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`
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.Respuestas:
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 TABLE
como lo mencionó, pero debe preocuparse por lainnodb_file_per_table
variable:Dejame explicar:
Con las
OPTIMIZE TABLE
tablas 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
OPTIMIZE
declaració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
OPTIMIZE
proceso, 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 laOPTIMIZE
fase) 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 TABLE
declaración, laALTER TABLE
funcionará de la misma manera queOPTIMIZE TABLE
. Solo puedes usar:3. ALTERAR TABLA (EN LÍNEA)
El problema de
OPTIMIZE
yALTER TABLE
que 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 porqueALTER
es genial.Tenga en cuenta que debería haber hecho
FOREIGN KEY
referencia a su tabla, FK y desencadena el riesgo de producir un desastre. Para verificar estos requisitos previos, consulte:Así es como uso pt-online-schema-change:
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.
fuente
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:
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):
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
fuente