Estou tentando encontrar a melhor maneira de gerenciar tabelas particionadas do postgresql. Tenho duas tabelas particionadas (uma partição por dia, com base na coluna created_at
existente em ambas as tabelas) fridge_tagreading
e fridge_tagantennareading
. fridge_tagantennareading
referências fridge_tagreading
através de uma chave estrangeira composta (tag_reading_id, created_at)
.
Regularmente quero remover partições antigas. Para isso, minha ideia era fazer o seguinte (exemplo se para remoção de dados datados de 03/05/2024):
alter table fridge_tagantennareading detach partition fridge_tagantennareading_2024_may_03;
drop table fridge_tagantennareading_2024_may_03;
alter table fridge_tagreading detach partition fridge_tagreading_2024_may_03;
drop table fridge_tagreading_2024_may_03;
As duas primeiras consultas funcionam perfeitamente. No entanto, ao executar o terceiro, acertei meu statement_timeout
(atualmente definido como 10s). Parece que a consulta que verifica a violação de fk na tabela referenciada leva muito tempo:
select fk."tag_reading_id", fk."created_at"
from "public"."fridge_tagantennareading" fk
join
"public"."fridge_tagreading_2024_may_03" pk
on (
pk."id" operator(pg_catalog. =) fk."tag_reading_id"
and pk."created_at" operator(pg_catalog. =) fk."created_at"
)
where
(
(pk.created_at is not null)
and (pk.created_at >= '2024-05-03 00:00:00+00'::timestamp with time zone)
and (pk.created_at < '2024-05-04 00:00:00+00'::timestamp with time zone)
)
and (fk."tag_reading_id" is not null and fk."created_at" is not null)
;
Meu entendimento é que essa consulta leva muito tempo porque o postgres verifica todas as partições na tabela referenciada. Estou surpreso que o postgres não "propague restrições", o que levaria a uma consulta apenas na partição boa da tabela referenciada (isso seria muito rápido).
É uma limitação conhecida? Como você lidaria com tal situação? Minha única solução até agora parece eliminar a restrição de chave estrangeira...
Obrigado
Sim, esta é uma limitação conhecida. Tem que ser assim, porque o PostgreSQL precisa garantir que as chaves estrangeiras não sejam violadas.
Como ambas as tabelas particionadas parecem estar particionadas
created_at
, a solução simples seria definir a chave estrangeira entre as partições para o mesmo dia, em vez de na própria tabela particionada. Isso lhe daria as mesmas garantias e a separação de partições seria muito mais fácil.