Excluindo e recuperando espaço da tabela do InnoDB

14

Eu tenho uma tabela InnoDB de 700 GB na qual não estou gravando mais dados (apenas lendo). Gostaria de excluir os dados mais antigos que ele contém e recuperar esse espaço em disco (já que estou ficando sem). A parte de exclusão é bastante fácil, porque eu tenho um índice primário de auto-inc. Para que eu possa iterar em pedaços usando-o e excluir as linhas, mas isso não me trará de volta o espaço. Suponho que OPTIMIZE TABLEvai, mas isso pode levar uma eternidade em uma mesa de 700 GB, então existe outra opção que estou ignorando?

Editado por RolandoMySQLDBA

Supondo que sua tabela seja mydb.mytable, execute a seguinte consulta e publique-a aqui para poder determinar o espaço em disco necessário para o encolhimento da tabela:

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;

Também precisamos ver a estrutura da tabela, se permitido.

Editar por Noam

Esta é a saída da consulta:

datsize ndxsize tblsize
682,51 47,57 730,08

Esta é a estrutura da tabela ( 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`
Noam
fonte
Você tem outro volume de disco para capturar apenas os dados ???
RolandoMySQLDBA
@RolandoMySQLDBA Eu tenho um disco rígido externo que posso montar. Isso conta?
Noam
@RolandoMySQLDBA mas faria de-curso como uma opção para excluir algum espaço sem a necessidade de ter outro 700GB
Noam
@RolandoMySQLDBA o tamanho extra do disco causa problemas de desempenho?
Aris
@ Aris pode depender do disco e do tempo de busca. Hoje em dia, a maioria dos discos tem um desempenho melhor agora, mas de que adianta desperdiçar ciclos (mesmo indo muito rápido) se você tiver grandes bolsões esparsos de espaço em disco na sua mesa ???. Isto é especialmente verdade para o InnoDB, que normalmente é fixado em blocos de 16K. Com a fragmentação interna de blocos de 16K, convém desfragmentar a tabela usando ALTER TABLE ... ENGINE=InnoDB;(se você tiver espaço para isso). A maioria está satisfeita com seus SSDs muito rápidos e não se preocupa mais.
RolandoMySQLDBA

Respostas:

21

Essa é uma boa pergunta. Você tem várias soluções, mas sua mesa é bastante grande, então nenhuma ficará sem dor :)

Você tem três soluções para "reduzir" as tabelas do InnoDB:

1. OTIMIZAR A TABELA

Você pode usar OPTIMIZE TABLEcomo você mencionou, mas deve se preocupar com a innodb_file_per_tablevariável:

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

Deixe-me explicar:

Com as OPTIMIZE TABLEtabelas do InnoDB, bloqueia a tabela, copia os dados em uma nova tabela limpa (é por isso que o resultado é reduzido), descarta a tabela original e renomeia a nova tabela com o nome original. É por isso que você deve ter o dobro da volumetria da sua tabela disponível em seu disco (durante a operação, você precisará de 2x700 GB).

Quando você estiver no innodb_file_per_table = ON. Todas as tabelas possuem um arquivo de dados adequado. Portanto, a OPTIMIZEinstrução criará um novo arquivo de dados (~ 700 GB) quando a operação for concluída, o MySQL descartará o original e renomeará o novo (assim, no final, os 700 GB - provavelmente menos porque serão encolhidos - de dados gerado durante a operação)

Quando você estiver no innodb_file_per_table = OFF. Todos os dados vão para um arquivo de dados: ibdata . Este arquivo tem uma particularidade triste, não pode ser reduzido. Portanto, durante o OPTIMIZEprocesso, sua nova tabela será criada (perto de 700 GB), mas mesmo após a operação de remoção e renomeação (e no final da OPTIMIZEfase), o ibdata não lançará os ~ 700 GB; portanto, você deseja liberar alguns dados, mas possui 700 GB mais legal, não é?

2. ALTER TABLE

Você também pode usar uma ALTER TABLEdeclaração, ALTER TABLEa mesma funcionará da mesma forma que OPTIMIZE TABLE. Você pode apenas usar:

ALTER TABLE myTable EGINE=InnoDB;

3. ALTER TABLE (ONLINE)

O problema OPTIMIZEe ALTER TABLEo travamento da tabela durante a operação. Você pode usar a ferramenta Percona: pt-online-schema-change (do Percona Toolkit: link ). pt-online-schema ... construirá um mecanismo com gatilhos e tabela temporária que permite que a tabela original esteja disponível para leitura e gravação durante a operação. Eu uso essa ferramenta na produção para o grande ALTER, é muito legal.

Observe que você deve ter feito FOREIGN KEYreferência à sua tabela, FK e dispara o risco de produzir uma bagunça. Para verificar esses pré-requisitos, consulte:

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

Aqui está como eu uso pt-online-schema-change:

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

Observe que minha observação sobre innodb_file_per_table também é verdadeira para esta solução.

4. mysqldump

A última solução é recriar todos os bancos de dados de um despejo. Terrivelmente longo, mas terrivelmente eficiente. Observe que é a única solução para "reduzir" o arquivo ibdata.

Máx.

Maxime Fouilleul
fonte
Também na opção de alteração de tabela on-line da ferramenta percona, precisarei de 700 GB de espaço livre em disco?
Noam
Sim, o pt-online apenas usa algum mecanismo para fazer o ALTER online, mas faz um ALTER de qualquer maneira.
Maxime Fouilleul
@MaximeFouilleul, o tamanho extra do disco causa problemas de desempenho?
Aris
1

Se você tem pouco tamanho de disco, sugiro que você faça exatamente o que Max sugeriu com pt-online-schema-change (ONLINE). Eu estive na mesma situação com uma tabela muito menor (200 GB) e escolhi fazer alguma compactação ao mesmo tempo. Algo nesse sentido deve funcionar:

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

Isso funcionará apenas se você estiver no formato de arquivo barracuda e no formato COMPACT da tabela. Além disso, você deve ter innodb_file_per_table ativado. Isso pode surpreender o tamanho da sua tabela, especialmente se houver muito texto e se você usar KEY_BLOCK_SIZE menor, como 8K ou até 4K (o padrão é 16K). Você também pode verificar quanto espaço você pode ganhar com vários benchmarks em relação a esse problema em outros blogs, mas a documentação do MySQL anuncia 25% a 50% (quase 90% para mim).

Observe que isso também pode afetar o desempenho ao executar SELECTs (da documentação do MySQL):

Assim, a qualquer momento, o buffer pool pode conter as formas compactada e descompactada da página, ou apenas a forma compactada da página, ou nenhuma.

O MySQL também precisa descompactar os dados quando não estiver no buffer pool. Então esteja avisado.

Isso realmente funcionou bem no meu caso. Eu tive um texto longo. 200GB tornaram-se 26GB. Performances não foram alteradas.

Para informações mais detalhadas, verifique estes links:

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

Emeric Hunter
fonte