Eu tenho uma tabela do InnoDB que desejo alterar. A tabela possui ~ 80 milhões de linhas e encerra alguns índices.
Quero alterar o nome de uma das colunas e adicionar mais alguns índices.
- Qual é a maneira mais rápida de fazer isso (supondo que eu possa sofrer até um tempo de inatividade - o servidor é um escravo não utilizado)?
- É uma
alter table
solução simples , a mais rápida?
Neste momento, tudo o que me interessa é a velocidade :)
mysql
innodb
alter-table
ddl
Correu
fonte
fonte
SHOW CREATE TABLE tblname\G
, mostre a coluna que precisa ser alterada, o tipo de dados da coluna e o novo nome para a coluna.sent_at
e para adicioná-la mais alguns índices # : 277Respostas:
Uma maneira segura de acelerar um ALTER TABLE é remover índices desnecessários
Aqui estão as etapas iniciais para carregar uma nova versão da tabela
Por favor observe o seguinte:
Larguei source_persona_index porque é a primeira coluna em outros 4 índices
Larguei target_persona_index porque é a primeira coluna em outros 2 índices
Larguei target_persona_relation_type_index porque as 2 primeiras colunas também estão em target_persona_relation_type_message_id_index
OK Isso cuida de índices desnecessários. Existem índices com baixa cardinalidade? Aqui está o caminho para determinar isso:
Execute as seguintes consultas:
De acordo com sua pergunta, existem cerca de 80.000.000 de linhas. Como regra geral, o MySQL Query Optimizer não usará um índice se a cardinalidade das colunas selecionadas for maior que 5% da contagem de linhas da tabela. Nesse caso, isso seria 4.000.000.
COUNT(DISTINCT sent_at)
> 4.000.000ALTER TABLE s_relations_new DROP INDEX sent_at_index;
COUNT(DISTINCT message_id)
> 4.000.000ALTER TABLE s_relations_new DROP INDEX message_id_index;
COUNT(DISTINCT target_object_id)
> 4.000.000ALTER TABLE s_relations_new DROP INDEX target_object_index;
Depois de determinar a utilidade ou inutilidade desses índices, você pode recarregar os dados
É isso aí, né? NÃO !!!
Se o seu site estiver ativo o tempo todo, pode haver INSERTs sendo executados contra s_relations durante o carregamento de s_relations_new. Como você pode recuperar essas linhas ausentes?
Vá encontrar o ID máximo em s_relations_new e anexe tudo depois desse ID em s_relations. Para garantir que a tabela esteja congelada e usada apenas para esta atualização, você deve ter um pouco de tempo de inatividade para obter as últimas linhas que foram inseridas em s_relation_new. Aqui está o que você faz:
No sistema operacional, reinicie o mysql para que ninguém mais possa fazer login, exceto root @ localhost (desativa o TCP / IP):
Em seguida, efetue login no mysql e carregue as últimas linhas:
Então, reinicie o mysql normalmente
Agora, se você não pode derrubar o mysql, precisará fazer uma isca e alternar em s_relations. Apenas entre no mysql e faça o seguinte:
De uma chance !!!
CAVEAT: Quando estiver satisfeito com esta operação, você poderá soltar a tabela antiga assim que possível:
fonte
A resposta correta depende da versão do mecanismo MySQL que você está usando.
Se você estiver usando o 5.6+, renomear e adicionar / remover índices são executados online , ou seja, sem copiar todos os dados da tabela.
Apenas use
ALTER TABLE
como de costume, será quase instantâneo para renomear e eliminar índices e razoavelmente rápido para adicionar índices (tão rápido quanto ler uma vez toda a tabela).Se você estiver usando 5.1+ e o plug-in InnoDB estiver ativado, a adição / remoção de índices também estará online. Não tenho certeza sobre renomear.
Se estiver usando a versão mais antiga,
ALTER TABLE
ainda será o mais rápido - mas provavelmente será terrivelmente lento porque todos os seus dados serão reinseridos em uma tabela temporária sob o capô.Finalmente, é hora de desmistificar mitos. Infelizmente, não tenho carma suficiente aqui para comentar as respostas, mas acho importante corrigir a resposta mais votada. Isto está errado :
Na verdade, é o contrário .
Os índices são úteis para selecionar poucas linhas, por isso é importante que eles tenham alta cardinalidade, o que significa muitos valores distintos e estatisticamente poucas linhas com o mesmo valor.
fonte
RENAME TABLE
instantâneo (conforme o esperado), masCHANGE COLUMN
a renomear a chave primária fez uma cópia completa ... 7 horas! Possivelmente apenas porque era a chave primária? Não é bom.Eu tive o mesmo problema com o Maria DB 10.1.12. Depois de ler a documentação, descobri que há uma opção para executar a operação "no local", que elimina a cópia da tabela. Com esta opção, a tabela de alteração é muito rápida. No meu caso, foi:
isso é muito rápido. Sem a opção de algoritmo, nunca terminaria.
https://mariadb.com/kb/en/mariadb/alter-table/
fonte
Para a coluna renomear,
deve estar bem e não deve ter nenhum tempo de inatividade.
Para os índices, a instrução CREATE INDEX bloqueará a tabela. Se é um escravo não utilizado, como você mencionou, isso não é problema.
Uma outra opção seria criar uma tabela totalmente nova com nomes e índices de coluna adequados. Em seguida, você pode copiar todos os dados para ele e executar uma série de
Isso minimizaria o tempo de inatividade com o custo de usar temporariamente o dobro do espaço.
fonte
Eu também tenho esse problema e usei este SQL:
Espero que ajude alguém
Saudações,
Vai
fonte