Não parece haver um método genérico suportado, mas existem alguns truques que podem ser usados em contextos limitados para avaliar o progresso de uma consulta individual. Aqui estão alguns deles.
Sequências
Quando uma consulta SELECT ou UPDATE inclui alguma nextval(sequence_name)
, ou um INSERT possui uma coluna de destino com um nextval
padrão, o valor atual da sequência pode ser consultado repetidamente em outra sessão com SELECT sequence_name.last_value
. Funciona porque as seqüências não são limitadas por transações. Quando o plano de execução é tal que a sequência é incrementada linearmente durante a consulta, ela pode ser usada como um indicador de progresso.
pgstattuple
O módulo contrg pgstattuple fornece funções que podem ser exibidas diretamente nas páginas de dados. Parece que quando as tuplas são inseridas em uma tabela vazia e ainda não confirmadas, elas são contadas no dead_tuple_count
campo a partir da pgstattuple
função.
Demo com 9.1: crie uma tabela vazia
CREATE TABLE tt AS (n numeric);
Vamos inserir 10 milhões de linhas nele:
INSERT INTO tt SELECT * FROM random() from generate_series(1,10000000);
Em outra sessão, verifique pgstattuple a cada segundo durante a inserção:
$ while true;
do psql -Atc "select dead_tuple_count from pgstattuple('tt')";
sleep 1;
done
Resultados:
0 0
69005
520035
1013430
1492210
1990415
2224625
2772040
3314460
3928660
4317345
4743770
5379430
6080950
6522915
7190395
7953705
8747725
9242045
0 0
Ele volta a 0 quando a inserção é concluída (todas as tuplas se tornam visíveis e ativas).
Esse truque também pode ser usado quando a tabela não é criada recentemente, mas dead_tuple_count
é provável que a inicial tenha um valor diferente de zero e também pode ser alterada simultaneamente se outra atividade de gravação, como o vácuo automático, estiver em andamento (presumivelmente? Não sabe ao certo qual nível de simultaneidade esperada com autovacuum).
No entanto, não pode ser usado se a tabela for criada pela própria instrução ( CREATE TABLE ... AS SELECT
ou SELECT * INTO newtable
), pois a criação é transacionada. A solução alternativa seria criar a tabela sem linhas (adicionar LIMIT 0
) e preenchê-la na próxima transação.
Observe que pgstattuple
isso não é gratuito: ele varre a mesa inteira a cada chamada. Também é limitado a superusuários.
Contador personalizado
No blog de Pavel Stehule, ele fornece uma função de contador implementada em C que gera AVISOS em um número especificado de execuções. Você precisa combinar a função com a consulta de alguma forma para permitir que o executor a chame. Os avisos são enviados durante a consulta e eles não precisam de uma sessão separada, apenas um cliente SQL que os exibe ( psql
sendo o candidato óbvio).
Exemplo de INSERT INTO retrabalhado para gerar avisos:
/* transformation */
INSERT INTO destination_table
SELECT (r).*
FROM (SELECT counter(to_destination_table(_source), 1000, true) r
FROM source _source) x
Pergunta relacionada sobre stackoverflow, para funções:
Como relatar o progresso da função PostgreSQL de longa execução para o cliente
Opções futuras?
Em maio de 2017, existe um patch promissor enviado à comunidade de desenvolvedores:
[PATCH v2] Comando Progress para monitorar a progressão de consultas SQL de longa execução
que pode acabar como uma solução genérica no PostgreSQL 11 ou posterior. Os usuários que desejam participar dos recursos de trabalho em andamento podem aplicar a versão mais recente do patch e tentar o PROGRESS
comando proposto .
pv
comando antes, e ele não estava instalado no meu servidor Debian por padrão, mas está no repositório. A descrição diz "pv (Pipe Viewer) pode ser inserido em qualquer pipeline normal entre dois processos para fornecer uma indicação visual da rapidez com que os dados estão passando". Um comando muito útil!