É possível atualizar uma visão materializada de forma incremental no PostgreSQL, ou seja, apenas para os dados que são novos ou alterados?
Considere esta tabela e visualização materializada:
CREATE TABLE graph (
xaxis integer NOT NULL,
value integer NOT NULL,
);
CREATE MATERIALIZED VIEW graph_avg AS
SELECT xaxis, AVG(value)
FROM graph
GROUP BY xaxis
Periodicamente, novos valores são adicionados graph
ou um valor existente é atualizado. Desejo atualizar a exibição a graph_avg
cada duas horas apenas para os valores que foram atualizados. No entanto, no PostgreSQL 9.3, toda a tabela é atualizada. Isso é bastante demorado. A próxima versão 9.4 permite CONCURRENT
atualização, mas ainda atualiza toda a visualização. Com centenas de milhões de linhas, isso leva alguns minutos.
Qual é uma boa maneira de acompanhar os valores atualizados e novos e apenas atualizar a exibição parcialmente?
Você sempre pode implementar sua própria tabela servindo como "visão materializada". Foi assim que fizemos antes de
MATERIALIZED VIEW
ser implementado no Postgres 9.3.Você pode criar uma planície
VIEW
:E materialize o resultado uma vez ou sempre que precisar recomeçar:
(Ou use a
SELECT
instrução diretamente, sem criar umVIEW
.)Então, dependendo dos detalhes não divulgados do seu caso de uso, você pode //
DELETE
alterar manualmente.UPDATE
INSERT
Uma instrução DML básica com CTEs de modificação de dados para sua tabela como está :
Supondo que ninguém mais tente escrever simultaneamente ( a
graph_avg
leitura não é problema):Receita básica
timestamp
coluna com padrãonow()
à sua tabela base. Vamos chamá-lots
.xaxis
ouvalue
.Crie uma pequena tabela para lembrar o carimbo de data/hora do seu último instantâneo. Vamos chamá-lo
mv
:Crie este índice parcial de várias colunas:
Use o carimbo de data/hora do último instantâneo como predicado em suas consultas para atualizar o instantâneo com o uso de índice perfeito.
No final da transação, elimine o índice e recrie-o com o carimbo de data/hora da transação substituindo o carimbo de data/hora no predicado do índice (inicialmente
'-infinity'
), que você também salva em sua tabela. Tudo em uma transação.Observe que o índice parcial é ótimo para cobrir
INSERT
eUPDATE
operações, mas nãoDELETE
. Para cobrir isso, você precisa considerar a tabela inteira. Tudo depende dos requisitos exatos.Atualização simultânea (Postgres 9.4)
Embora não seja uma atualização incremental como você pediu, o Postgres 9.4 fornece um novo recurso de atualização simultânea .
Para citar o documento…
Esta atualização simultânea ainda está executando uma nova consulta completa (não incremental). Portanto, CONCURRENTLY não economiza no tempo total de computação, apenas minimiza a quantidade de tempo que sua visualização materializada fica indisponível para uso durante sua atualização.