No parece haber un método genérico compatible, pero hay algunos trucos que se pueden usar en contextos limitados para evaluar el progreso de una consulta individual. Éstos son algunos de ellos.
Secuencias
Cuando una consulta SELECT o UPDATE incluye alguna nextval(sequence_name)
, o un INSERT tiene una columna de destino con un nextval
valor predeterminado, el valor de secuencia actual se puede consultar repetidamente en otra sesión conSELECT sequence_name.last_value
. Funciona porque las secuencias no están delimitadas por transacciones. Cuando el plan de ejecución es tal que la secuencia se incrementa linealmente durante la consulta, puede usarse como un indicador de progreso.
pgstattuple
El módulo contrib pgstattuple proporciona funciones que pueden ver directamente las páginas de datos. Parece que cuando las tuplas se insertan en una tabla vacía y aún no se confirman, se cuentan en el dead_tuple_count
campo desde la pgstattuple
función.
Demostración con 9.1: crea una tabla vacía
CREATE TABLE tt AS (n numeric);
Insertemos 10M filas en él:
INSERT INTO tt SELECT * FROM random() from generate_series(1,10000000);
En otra sesión, verifique pgstattuple cada segundo durante la inserción:
$ 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
Vuelve a 0 cuando finaliza la inserción (todas las tuplas se vuelven visibles y vivas).
Este truco también se puede usar cuando la tabla no se ha creado recientemente, pero dead_tuple_count
es probable que la inicial tenga un valor distinto de cero y también puede cambiar simultáneamente si está ocurriendo otra actividad de escritura como el vacío automático (¿presumiblemente? ¿No está seguro de qué nivel de concurrencia a esperar con autovacuum).
Sin embargo, no se puede usar si la tabla es creada por la declaración misma ( CREATE TABLE ... AS SELECT
o SELECT * INTO newtable
), ya que la creación se transa. La solución alternativa sería crear la tabla sin filas (agregar LIMIT 0
) y completarla en la próxima transacción.
Tenga en cuenta que pgstattuple
no es gratis: escanea toda la tabla en cada llamada. También se limita a los superusuarios.
Contador personalizado
En el blog de Pavel Stehule, proporciona una función de contador implementada en C que genera AVISOS en un número específico de ejecuciones. Debe combinar la función con la consulta de alguna manera para permitir que el ejecutor la llame. Los avisos se envían durante la consulta y no necesitan una sesión separada, solo un cliente SQL que los muestre ( psql
siendo el candidato obvio).
Ejemplo de INSERT INTO reelaborado para generar avisos:
/* transformation */
INSERT INTO destination_table
SELECT (r).*
FROM (SELECT counter(to_destination_table(_source), 1000, true) r
FROM source _source) x
Pregunta relacionada sobre stackoverflow, para funciones:
cómo informar el progreso de la función PostgreSQL de larga duración al cliente
Opciones de futuro?
A partir de mayo de 2017, hay un parche prometedor enviado a la comunidad de desarrolladores:
[PATCH v2] Comando de progreso para monitorear la progresión de consultas SQL de larga ejecución
que podría terminar como una solución genérica en PostgreSQL 11 o posterior. Los usuarios que desean participar en las funciones de trabajo en progreso pueden aplicar la última versión del parche y probar el PROGRESS
comando propuesto .
pv
comando antes, y no estaba instalado en mi servidor Debian por defecto, pero está en el repositorio. La descripción dice que "pv (Pipe Viewer) se puede insertar en cualquier canalización normal entre dos procesos para dar una indicación visual de qué tan rápido pasan los datos". Un comando muy útil!