Eu sou um desenvolvedor PHP, então não seja rigoroso. Eu tenho uma grande mesa ~ 5,5 GB de despejo. Nosso PM decidiu fazer uma nova coluna nela para realizar novo recurso. A tabela é InnoDB, então o que eu tentei:
Alterar tabela na tela com bloqueio de mesa. Demorou ~30 horas e nada. Então eu simplesmente parei. Primeiro cometi um erro porque não finalizei todas as transações, mas na segunda vez não houve multilock. Estado era
copy to tmp table
.Como também preciso aplicar particionamento para esta tabela, decidimos fazer dump, renomear e fazer tabela com o mesmo nome e nova estrutura. Mas o dump está fazendo uma cópia estrita (pelo menos não encontrei outra coisa). Então eu adicionei para despejar uma nova coluna
sed
e consultá-la. Mas alguns erros estranhos começaram. Eu acredito que foi causado por charset. A tabela em utf-8 e o arquivo se tornaram us-ascii apóssed
. Então, recebi erros (comando desconhecido '\'') em 30% dos dados. Então esse também é um mau caminho.
Quais são as outras opções para fazer isso e acelerar o desempenho (eu posso fazer isso com script php, mas levará muito tempo). Qual será o desempenho de INSERT SELECT
neste caso.
Obrigado por qualquer adiantamento.
Use o MySQL Workbench . Você pode clicar com o botão direito do mouse em uma tabela e selecionar "Enviar para o Editor SQL" -> "Criar instrução". Desta forma, nenhuma "propriedade" da tabela será esquecida de adicionar (incluindo
CHARSET
ouCOLLATE
).Com essa enorme quantidade de dados, recomendo limpar a tabela ou a estrutura de dados que você usa (um bom DBA é útil). Se não for possível:
ALTER
) e crie uma nova com oCREATE
script que você obtém do Workbench. Você também pode estender essa consulta com o novo campo necessárioDesta forma você evita indexar/etc para rodar registro por registro. A "atualização" da tabela ainda será lenta (já que a quantidade de dados é enorme), mas essa é a maneira mais rápida que consigo pensar.
EDIT: Leia este artigo para obter detalhes sobre os comandos usados na consulta de exemplo acima ;)
alter table add column, algorithm=inplace, lock=none
irá alterar uma tabela MySQL 5.6 sem copiar a tabela e sem travar o impacto.Acabei de testar isso ontem, a massa inseriu 70 mil linhas em uma tabela de partição de 280 mil linhas 7, 10 mil linhas em cada partição, com 5 segundos de suspensão entre eles para permitir outra taxa de transferência.
Iniciou as inserções em massa e, em uma sessão separada, iniciou a
alter
instrução on-line acima no MySQL Workbench,alter
terminou antes das inserções, duas novas colunas foram adicionadas e nenhuma linha resultou da alteração, significando que o MySQL não copiou nenhuma linha.Sua ideia do sed é um método decente, mas sem os erros ou o comando que você executou, não podemos ajudá-lo.
No entanto, um método bem conhecido para fazer alterações online em tabelas grandes é pt-online-schema-change . A visão simplista do que essa ferramenta faz é copiada da documentação:
Esse método também pode demorar um pouco para ser concluído, mas durante o processo a tabela original será completamente utilizável.
Acho que o Mydumper/Myloader é uma boa ferramenta para operações como esta: Está melhorando a cada dia. Você pode utilizar suas CPUs e carregar dados em paralelo: http://www.percona.com/blog/2014/03/10/new-mydumper-0-6-1-release-offers-several-performance-and- recursos de usabilidade/
Eu consegui carregar centenas de tabelas MySQL de gigabytes em horas.
Agora, quando se trata de adicionar uma nova coluna, é complicado, pois o MySQL copia toda a tabela para a
TMP
área de memória comALTER TABLE...
Embora o MySQL 5.6 diga que pode fazer alterações de esquema online, não consegui fazê-las online para tabelas massivas sem bloqueio disputa ainda.Atualmente, a melhor opção para alterar tabelas enormes é provavelmente https://github.com/github/gh-ost
gh-ost é uma solução de migração de esquema online sem gatilho para MySQL. É testável e oferece capacidade de pausa, controle/reconfiguração dinâmica, auditoria e muitas vantagens operacionais.
gh-ost produz uma carga de trabalho leve no mestre durante a migração, desacoplada da carga de trabalho existente na tabela migrada.
Ele foi projetado com base em anos de experiência com soluções existentes e muda o paradigma das migrações de tabelas.
acabei de ter o mesmo problema. Uma pequena solução alternativa:
CREATE TABLE nova_tabela SELECT * FROM tabela antiga;
DELETE DE nova_tabela
ALTER TABLE nova_tabela ADD COLUMN nova_coluna int(11);
INSERT INTO new_table select *, 0 from old_table
soltar tabela tabela_antiga; renomear tabela new_table TO old_table;