Skip to main content
A maioria das consultas ALTER TABLE modifica configurações da tabela ou dados:
A maioria das consultas ALTER TABLE é suportada apenas para tabelas *MergeTree, Merge e Distributed.
Estas instruções ALTER manipulam views: Estas instruções ALTER modificam entidades relacionadas ao Controle de Acesso Baseado em Funções:

Combinando ações em um único ALTER

Uma única instrução ALTER TABLE aceita várias ações separadas por vírgulas. Assim, o que exigiria uma sequência de instruções pode ser feito em uma só:
As ações não precisam ser do mesmo tipo e são aplicadas da esquerda para a direita. Assim, uma ação pode usar o que outra ação anterior adicionou:
Quando um cliente aguarda a conclusão de uma instrução ALTER, a configuração que controla essa espera depende da ação executada, não da instrução em si: ações que seguem o caminho de execução de mutações, como MATERIALIZE INDEX, são controladas por mutations_sync, enquanto ações sobre metadados são controladas por alter_sync. Portanto, combinar esses dois tipos de ação não faz com que sejam controlados pela mesma configuração. Consulte Sincronia das consultas ALTER para saber quais ações cada configuração abrange e Combinação de cláusulas MATERIALIZE INDEX para entender a restrição imposta a uma instrução que combina esses tipos de ação em um banco de dados Replicated.

Mutações

Consultas ALTER destinadas a manipular dados de tabelas são implementadas por meio de um mecanismo chamado “mutações”, principalmente ALTER TABLE … DELETE e ALTER TABLE … UPDATE. Elas são processos assíncronos em segundo plano, semelhantes às mesclagens em tabelas MergeTree, que produzem novas versões “mutadas” das partes. Para tabelas *MergeTree, as mutações são executadas por reescrita de partes de dados inteiras. Não há atomicidade — as partes são substituídas por partes mutadas assim que ficam prontas, e uma consulta SELECT iniciada durante uma mutação verá dados de partes que já foram mutadas junto com dados de partes que ainda não foram mutadas. As mutações são totalmente ordenadas pela ordem de criação e são aplicadas a cada parte nessa ordem. As mutações também têm uma ordenação parcial em relação às consultas INSERT INTO: os dados inseridos na tabela antes de a mutação ser enviada serão mutados, e os dados inseridos depois disso não serão mutados. Observe que as mutações não bloqueiam inserts de forma alguma. Uma consulta de mutação retorna imediatamente após a entrada da mutação ser adicionada (no caso de tabelas replicadas, ao ZooKeeper; no caso de tabelas não replicadas, ao sistema de arquivos). A mutação em si é executada de forma assíncrona usando as configurações do perfil do sistema. Para acompanhar o progresso das mutações, você pode usar a tabela system.mutations. Uma mutação enviada com sucesso continuará a ser executada mesmo que os servidores ClickHouse sejam reiniciados. Não há como reverter a mutação depois que ela é enviada, mas, se a mutação ficar travada por algum motivo, ela pode ser cancelada com a consulta KILL MUTATION. As entradas de mutações concluídas não são excluídas imediatamente (o número de entradas preservadas é determinado pelo parâmetro do motor de armazenamento finished_mutations_to_keep). Entradas de mutação mais antigas são excluídas.

Custo de execução e conclusão

Ao planejar um ALTER TABLE, diferencie uma alteração de metadados do trabalho necessário sobre as partes de dados existentes. Se o cliente aguarda ou não a conclusão depende da operação: alter_sync controla operações de metadados e MODIFY COLUMN, incluindo conversões de tipos que reescrevem dados; mutations_sync controla mutações em segundo plano, como UPDATE, DELETE e MATERIALIZE .... Não use durações fixas como referência operacional: o custo depende do volume de metadados, das partes e bytes afetados, do custo de conversão e da carga atual em segundo plano.

Sincronia das consultas ALTER

Por padrão, as consultas ALTER em tabelas não replicadas aguardam a conclusão do trabalho. Com alter_sync = 0, uma consulta ALTER que executa trabalho em segundo plano pode retornar antes que esse trabalho termine. Para tabelas replicadas, a consulta adiciona instruções para as ações apropriadas ao ZooKeeper, e as próprias ações são executadas assim que possível. A consulta pode aguardar a conclusão dessas ações em todas as réplicas. Para consultas ALTER que criam mutações pelo caminho de execução de mutações (incluindo, entre outras, UPDATE, DELETE, MATERIALIZE INDEX, MATERIALIZE PROJECTION, MATERIALIZE COLUMN, APPLY DELETED MASK, APPLY PATCHES, CLEAR STATISTIC e MATERIALIZE STATISTIC), a sincronia é definida pela configuração mutations_sync. Para outras consultas ALTER, incluindo reescritas com MODIFY COLUMN, a configuração alter_sync controla a espera. Você pode especificar por quanto tempo (em segundos) aguardar que réplicas inativas executem todas as consultas ALTER com a configuração replication_wait_for_inactive_replica_timeout.
Para todas as consultas ALTER, se alter_sync = 2 e algumas réplicas permanecerem inativas por mais tempo do que o especificado na configuração replication_wait_for_inactive_replica_timeout, uma exceção UNFINISHED será lançada. Com alter_sync = 3, não se aguarda pelas réplicas inativas, portanto nenhuma exceção é lançada.

Atribuição simultânea de ALTER em uma tabela

Em tabelas replicadas, enviar várias instruções ALTER separadas para a mesma tabela em rápida sucessão pode falhar com CANNOT_ASSIGN_ALTER (código 517). O caminho de replicação gera esse erro quando a réplica ainda não aplicou alguns ALTERs anteriores (a versão dos metadados ainda está defasada em relação aos metadados comuns — o servidor pode informar que a réplica “ainda não aplicou alguns dos alters anteriores” ou “Provavelmente há muitos alters sendo executados simultaneamente”). Essa condição pode persistir mesmo depois que um ALTER anterior já tiver sido atribuído. Trata-se de uma condição geral de ALTER de metadados / mutação simultâneos — não se limita a instruções que envolvem apenas mutações. Alterações simultâneas comuns de metadados (ADD / DROP / MODIFY e similares) podem gerar o mesmo código passível de nova tentativa (consulte, por exemplo, o caminho de nova tentativa abordado em tests/queries/0_stateless/03518_alter_logical_race.sh). Abordagens para evitar a condição de corrida:
  • Combine operações de metadados independentes em um único ALTER com várias cláusulas quando a gramática permitir (por exemplo, várias cláusulas ADD INDEX), conforme descrito em Combinando ações em um único ALTER.
  • Serialize as instruções ALTER e tente novamente ao receber o código 517 até que os ALTERs anteriores tenham sido aplicados na réplica.
  • Para ALTERs que geram mutações, aguarde a conclusão da mutação anterior usando um indicador documentado, como mutations_sync ou is_done em system.mutations, antes de enviar o próximo.

Combinação de cláusulas MATERIALIZE INDEX

Várias cláusulas MATERIALIZE INDEX podem aparecer em um único ALTER. O caso coberto no repositório é combinar várias cláusulas ADD INDEX com MATERIALIZE INDEX para esses mesmos novos índices em uma única instrução (consulte tests/queries/0_stateless/02911_add_index_and_materialize_index.sql). Essa forma combinada de ADD INDEX + MATERIALIZE INDEX mistura um segmento AlterCommand com um segmento MutationCommand; portanto, é rejeitada por DatabaseReplicated com QUERY_IS_PROHIBITED (InterpreterAlterQuery::validateReplicatedDatabaseSegments). Considere o exemplo 02911 válido para bancos de dados comuns (não DatabaseReplicated); em DatabaseReplicated, mantenha as alterações de metadados e as mutações de materialização em instruções separadas. Na implementação atual, cada cláusula MATERIALIZE INDEX é resolvida com base no snapshot dos metadados da tabela quando a mutação é preparada. Portanto, formas com várias cláusulas somente de materialização em índices já existentes seguem o mesmo caminho de preparação (somente mutação, portanto permanecem em um único segmento). Essa forma exata ainda não é coberta por um teste específico sem estado; trate-a como comportamento da implementação atual, e não como um contrato garantido separadamente, até que essa cobertura exista. Se precisar que as mutações sejam aplicadas em ordem, ainda é possível emitir um MATERIALIZE INDEX por instrução e aguardar usando mutations_sync.