Preciso migrar duas tabelas muito grandes continuamente. Minha primeira solução foi comparar coluna por coluna para descobrir o que havia mudado, mas isso é muito caro de executar.
A segunda ideia foi criar Colunas Computacionais PERSISTIDAS para armazenar valores com hash de colunas definidas. Isso poderia acelerar o processo. Mas o problema está no hash de colunas com timestamp e fuso horário. Estou recebendo este erro: ERROR: generation expression is not immutable
.
Tentei várias maneiras de converter o valor, mas nada está funcionando ainda.
Código (valores comentados, não funcionou):
ALTER TABLE schema.table ADD COLUMN hashed_columns UUID GENERATED ALWAYS AS (
md5(
id::text ||
type_id::text ||
--EXTRACT(EPOCH FROM date)::text ||
-- to_char(date::timestamp without time zone , 'YYYY-MM-DD"T"HH24:MI:SS') ||
-- date::text ||
-- to_char(date, 'YYYYMMDD')::integer ||
-- md5(date::text) ||
to_char(date, 'YYYYMMDD') ||
value1::text ||
value2::text
)::uuid
) STORED;
Parece que ele detecta uma coluna imutável e simplesmente gera um erro, sem tentar convertê-la primeiro. O que estou tentando fazer é fundamentalmente errado ou é possível?
Quando removo a coluna de data do script, funciona, então o problema está no registro de data e hora.
O servidor está executando o Postgre 16.
Se você quiser ter uma
IMMUTABLE
expressão que convertatimestamp with time zone
algo que você pode concatenar, useNão acho que seja uma boa ideia nomear uma coluna de registro de data e hora
date
, mas isso é só um detalhe.Para o seu problema original: em vez de calcular um hash de todas as colunas ou comparar todas elas, por que você não adiciona simplesmente uma coluna
version
preenchida com um valor de sequência ou com o carimbo de data/hora atual em cadaUPDATE
coluna? Assim, você poderia comparar apenas com essa coluna para descobrir se a linha foi alterada ou não. Isso seria muito mais barato do que calcular o hash.Se entendi a tarefa corretamente, eu me aventuraria a sugerir este método. Adicione uma nova coluna à tabela (booleano é suficiente). Ao inserir novas linhas (alterando as existentes), escreva False. Após a transferência, atribua True. Para identificar os dados alterados, é realizada uma busca em uma única coluna.
Se você não gostar desse método ou se sentir desconfortável com ele, responderei à sua pergunta. Precisamos tornar sua coluna imutável. Você pode fazer isso colocando-a em uma função separada, cujos parâmetros serão os campos necessários para o processamento:
Coloque todos os seus cálculos na própria função e obtenha o resultado na coluna:
Se houver alguma falha sintática, não será difícil corrigi-la.
Fiz um exemplo simples (apenas um parâmetro, a lógica é preservada):