Eu tenho um banco de dados com número de tabelas.
Quero excluir alguns registros das tabelas, digamos que o número de registros seja superior a 20K ou 50K.
Todas as tabelas são InnoDB. E file_per_table
está desligado .
Quando excluir os registros de várias tabelas, haverá fragmentação nas tabelas.
Existe alguma maneira de remover a fragmentação.?
Atualização em 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)
Então agora minha pergunta é como eu decidirei que minhas tabelas estão fragmentadas ou não.
Respostas:
Eu resolvi isso no StackOverflow em outubro de 2010 .
Lembre-se do arquivo mais ocupado da infraestrutura do InnoDB: / var / lib / mysql / ibdata1
Esse arquivo normalmente abriga quatro tipos de informações
A execução
OPTIMIZE TABLE
em uma tabela do InnoDB armazenada no ibdata1 faz duas coisas:Embora você possa segregar dados da tabela e índices da tabela do ibdata1 e gerenciá-los independentemente usando innodb_file_per_table , a grande quantidade de espaço em disco no ibdata1 simplesmente não desaparece e não pode ser recuperada. Você deve fazer mais.
Para encolher ibdata1 uma vez por todas você deve fazer o seguinte:
1) MySQLDump todos os bancos de dados em um arquivo de texto SQL (chame-o /root/SQLData.sql)
2) Solte todos os bancos de dados (exceto o esquema mysql)
3) mysql de desligamento
4) Adicione as seguintes linhas ao /etc/my.cnf
Nota: Qualquer que seja o seu conjunto para innodb_buffer_pool_size, verifique se innodb_log_file_size é 25% de innodb_buffer_pool_size.
5) Exclua ibdata1, ib_logfile0 e ib_logfile1
Neste ponto, deve haver apenas o esquema mysql em / var / lib / mysql
6) Reinicie o mysql
Isso recriará o ibdata1 em 10 ou 18MB (dependendo da versão do MySQL), ib_logfile0 e ib_logfile1 em 1G cada
7) Recarregue /root/SQLData.sql no mysql
ibdata1 aumentará, mas conterá apenas metadados da tabela. De fato, crescerá muito lentamente ao longo dos anos. A única maneira de o crescimento do ibdata1 rapidamente é se você tiver um ou mais dos seguintes itens:
CREATE TABLE
,DROP TABLE
,ALTER TABLE
)Cada tabela do InnoDB existirá fora do ibdata1
Suponha que você tenha uma tabela do InnoDB chamada mydb.mytable. Se você acessar / var / lib / mysql / mydb, verá dois arquivos representando a tabela
O ibdata1 nunca mais conterá dados e índices do InnoDB.
Com a opção innodb_file_per_table em /etc/my.cnf, você pode executar
OPTIMIZE TABLE mydb.mytable;
e o arquivo /var/lib/mysql/mydb/mytable.ibd realmente diminui.Eu fiz isso muitas vezes na minha carreira como um DBA MySQL
De fato, na primeira vez em que fiz isso, reduzi um arquivo ibdata1 de 50 GB em 500 MB.
De uma chance. Se você tiver mais perguntas sobre isso, envie-me um email. Confie em mim. Isso funcionará a curto prazo e a longo prazo !!!
UPDATE 2012-04-19 09:23 EDT
Após executar as etapas acima, como você pode determinar quais tabelas precisam ser desfragmentadas? É possível descobrir, mas você terá um script.
Aqui está um exemplo: Suponha que você tenha a tabela
mydb.mytable
. Com innodb_file_per_table ativado, você tem o arquivo /var/lib/mysql/mydb/mytable.ibdVocê terá que recuperar dois números
FILESIZE NO SO: Você pode verificar o tamanho do arquivo no SO dessa maneira
FILESIZE FROM INFORMATION_SCHEMA: Você pode verificar o tamanho do arquivo de information_schema.tables como este:
Apenas subtraia o valor de INFORMAÇÃO_SCHEMA do valor do SO e divida a diferença pelo valor de INFORMAÇÃO_SCHEMA.
A partir daí, você decidiria qual porcentagem considera necessário desfragmentar essa tabela. Obviamente, você desfragmenta-o usando um dos seguintes comandos:
ou
fonte
Se você excluir linhas com freqüência (ou atualizar linhas com tipos de dados de comprimento variável), poderá acabar com muito espaço desperdiçado em seu (s) arquivo (s) de dados, semelhante à fragmentação do sistema de arquivos.
Se você não estiver usando a
innodb_file_per_table
opção, a única coisa que poderá fazer é exportar e importar o banco de dados, um procedimento que exige muito tempo e disco.Mas se você estiver usando
innodb_file_per_table
, poderá identificar e recuperar esse espaço!Antes da 5.1.21, o contador de espaço livre estava disponível na coluna table_comment de information_schema.tables. Aqui está algum SQL para identificar tabelas com pelo menos 100M (na verdade 97.65M) de espaço livre:
A partir do 5.1.21, isso foi movido para a coluna data_free (um local muito mais apropriado):
Você pode recuperar o espaço perdido, reconstruindo a tabela. A melhor maneira de fazer isso é usar 'alterar tabela' sem alterar nada:
É o que o MySQL faz nos bastidores se você executar 'optimize table' em uma tabela do InnoDB. Isso resultará em um bloqueio de leitura, mas não em um bloqueio de tabela completo. Quanto tempo leva depende completamente da quantidade de dados na tabela (mas não do tamanho do arquivo de dados). Se você possui uma tabela com um grande volume de exclusões ou atualizações, convém executá-la mensalmente ou semanalmente.
fonte