Tengo una base de datos que tiene varias tablas.
Quiero eliminar algunos registros de las tablas que dicen que el número de registros es más de 20K o 50K.
Todas las tablas son InnoDB. Y file_per_table
se fue .
Cuando elimine los registros de varias tablas, habrá fragmentación en las tablas.
¿Hay alguna forma de eliminar la fragmentación?
Actualización el 17 de abril
mysql> select TABLE_NAME, TABLE_SCHEMA, Data_free from information_schema.TABLES where TABLE_SCHEMA NOT IN ('information_schema', 'mysql') and Data_Free >0;
+-----------------+--------------+-----------+
| TABLE_NAME | TABLE_SCHEMA | Data_free |
+-----------------+--------------+-----------+
| City | world_innodb | 5242880 |
| City_Copy | world_innodb | 5242880 |
| Country | world_innodb | 5242880 |
| CountryLanguage | world_innodb | 5242880 |
| a | world_innodb | 5242880 |
| t1 | world_innodb | 5242880 |
| t2 | world_innodb | 5242880 |
+-----------------+--------------+-----------+
7 rows in set (0.00 sec)
Entonces, mi pregunta es cómo decidiré si mis tablas están fragmentadas o no.
Respuestas:
Abordé esto en StackOverflow en octubre de 2010 .
Tenga en cuenta el archivo más ocupado en la infraestructura de InnoDB: / var / lib / mysql / ibdata1
Este archivo normalmente contiene cuatro tipos de información
Ejecutar
OPTIMIZE TABLE
contra una tabla InnoDB almacenada en ibdata1 hace dos cosas:Si bien puede segregar los datos de la tabla y los índices de la tabla de ibdata1 y administrarlos de forma independiente utilizando innodb_file_per_table , la gran brecha de espacio en disco en ibdata1 simplemente no desaparecerá y no se puede reclamar. Debes hacer más.
Para reducir ibdata1 de una vez por todas , debe hacer lo siguiente:
1) MySQL Vuelca todas las bases de datos en un archivo de texto SQL (llámalo /root/SQLData.sql)
2) Descarte todas las bases de datos (excepto el esquema mysql)
3) Apagar mysql
4) Agregue las siguientes líneas a /etc/my.cnf
Nota al margen: cualquiera que sea su conjunto para innodb_buffer_pool_size, asegúrese de que innodb_log_file_size sea el 25% de innodb_buffer_pool_size.
5) Eliminar ibdata1, ib_logfile0 e ib_logfile1
En este punto, solo debe haber el esquema mysql en / var / lib / mysql
6) Reiniciar mysql
Esto recreará ibdata1 a 10 o 18 MB (dependiendo de la versión de MySQL), ib_logfile0 e ib_logfile1 a 1G cada uno
7) Recargar /root/SQLData.sql en mysql
ibdata1 crecerá pero solo contendrá metadatos de tabla. De hecho, crecerá muy lentamente con los años. La única forma en que ibdata1 crece rápidamente es si tiene uno o más de los siguientes:
CREATE TABLE
,DROP TABLE
,ALTER TABLE
)Cada tabla InnoDB existirá fuera de ibdata1
Supongamos que tiene una tabla InnoDB llamada mydb.mytable. Si accede a / var / lib / mysql / mydb, verá dos archivos que representan la tabla
ibdata1 nunca contendrá más datos e índices de InnoDB.
Con la opción innodb_file_per_table en /etc/my.cnf, puede ejecutar
OPTIMIZE TABLE mydb.mytable;
y el archivo /var/lib/mysql/mydb/mytable.ibd realmente se reducirá.He hecho esto muchas veces en mi carrera como DBA MySQL
De hecho, la primera vez que hice esto, colapsé un archivo ibdata1 de 50 GB en 500 MB.
Darle una oportunidad. Si tiene más preguntas sobre esto, envíeme un correo electrónico. Créeme. ¡Esto funcionará a corto plazo y a largo plazo!
ACTUALIZACIÓN 2012-04-19 09:23 EDT
Después de ejecutar los pasos anteriores, ¿cómo puede determinar qué tablas deben desfragmentarse? Es posible averiguarlo, pero tendrá un script.
Aquí hay un ejemplo: suponga que tiene la tabla
mydb.mytable
. Con innodb_file_per_table habilitado, tiene el archivo /var/lib/mysql/mydb/mytable.ibdTendrás que recuperar dos números
TAMAÑO DE ARCHIVO DESDE EL SO: Puede determinar el tamaño de archivo desde el SO de esta manera
FILESIZE FROM INFORMATION_SCHEMA: Puede determinar el tamaño del archivo desde information_schema.tables de esta manera:
Simplemente reste el valor de INFORMATION_SCHEMA del valor de OS y divida la diferencia entre el valor de INFORMATION_SCHEMA.
A partir de ahí, usted decidiría qué porcentaje considera necesario desfragmentar esa tabla. Por supuesto, lo desfragmenta con uno de los siguientes comandos:
o
fuente
Si elimina filas con frecuencia (o actualiza filas con tipos de datos de longitud variable), puede terminar con una gran cantidad de espacio desperdiciado en sus archivos de datos, similar a la fragmentación del sistema de archivos.
Si no está utilizando la
innodb_file_per_table
opción, lo único que puede hacer al respecto es exportar e importar la base de datos, un procedimiento que requiere mucho tiempo y disco.Pero si está usando
innodb_file_per_table
, ¡puede identificar y reclamar este espacio!Antes de 5.1.21, el contador de espacio libre está disponible en la columna table_comment de information_schema.tables. Aquí hay algunos SQL para identificar tablas con al menos 100M (en realidad 97.65M) de espacio libre:
A partir de 5.1.21, esto se movió a la columna data_free (un lugar mucho más apropiado):
Puede recuperar el espacio perdido reconstruyendo la tabla. La mejor manera de hacer esto es usar 'alter table' sin cambiar realmente nada:
Esto es lo que hace MySQL detrás de escena si ejecuta 'optimizar tabla' en una tabla InnoDB. Resultará en un bloqueo de lectura, pero no un bloqueo de tabla completo. El tiempo que tarda depende completamente de la cantidad de datos en la tabla (pero no del tamaño del archivo de datos). Si tiene una tabla con un alto volumen de eliminaciones o actualizaciones, es posible que desee ejecutarla mensualmente o incluso semanalmente.
fuente