2012-08-15 13 views
9

que tienen una aplicación cliente que utiliza C# Npgsql llamar a una función plpgsql en PostgreSQL 9.1.4. La función lleva mucho tiempo y me gustaría informar el progreso al cliente de alguna manera. ¿Cómo debería hacer esto?Cómo informe de situación de la función de PostgreSQL de larga duración a cliente

El mecanismo LISTEN/NOTIFY suena perfecto para esto, excepto que todo se ejecuta dentro de una transacción y los eventos NOTIFY no se envían hasta el final de la transacción, lo cual es inútil para mí.

La otra cosa que he intentado es levantar AVISO, que puedo procesar en el cliente, pero incluso los avisos parecen estar amortiguada por un tiempo y enviado por lotes. Es mejor que nada, pero no es ideal. ¿Hay alguna forma de que pueda "vaciarlos", para que sean enviados al cliente de inmediato?

Respuesta

6

No hay nada mejor que AVISO SUBIR.

Estas señales no están almacenadas en el búfer, y son asíncronas, probablemente tenga problemas en el procesamiento de avisos en su aplicación.

+0

Con PostgreSQL 8.4 y superior, también puede proporcionar un código de error para RAISE AVISO, que hace que sea más fácil distinguir entre los mensajes de progreso y otros avisos que podrían emitirse. –

+0

Tiene razón, resulta que las NOTIFICACIONES * se * entregaron a medida que se generaban, pero hubo una desaceleración muy extraña en la función, lo que no ocurrió cuando ejecuté la misma consulta directamente. He descubierto una solución para eso ahora. – EM0

+0

SUBIR AVISO tiene una sobrecarga significativa relativa - apretón de manos es la red entre el cliente y el servidor. Por lo general no plantea noto cada iteración, pero noto cada mil iteración. –

1

manera más simple sería la de dividir su función pgsql en varias subfunciones, que llamarlos de forma secuencial, la zona de aplicación, la gestión ámbito de transacción en la aplicación.

+0

Gracias, pero en este caso particular, no sería sencillo, te puedo asegurar. :) ¿Alguna otra forma? – EM0

+0

No es que se me ocurra, lo siento – mathieu

7

Además de @ excelente punto de Pavel sobre RAISE NOTICE, hay otra técnica clásica utilizada para monitorear el progreso de consulta en Pg. Es un truco, pero es bastante efectivo.

Puede aprovechar el hecho de que los cambios en las secuencias son inmediatamente visibles en todas partes para exponer el progreso de una función hacia el exterior. Utilice una secuencia codificada y asegúrese de que la función no se llame al mismo tiempo o pase el nombre de la secuencia de supervisión de progreso a la función.

Su función puede llamar al nextval(seqname) en cada iteración, y las partes interesadas pueden examinar el estado de la secuencia con SELECT last_value FROM seqname desde otra sesión.

que pueda tomar la secuencia de una cuenta atrás hasta la finalización de su puesta en marcha con

create sequence test maxvalue 2147483647 increment by -1; 

y llamando setval('seqname', num_items) en el inicio de su función. Luego, regresará hacia cero con cada llamada nextval. 2147483647 es maxint, por cierto.

No hace falta decir que esto no es portátil, y no hay garantía de que SELECT ing de una secuencia siempre funcione de esta manera. Aunque es muy útil.

+0

+ 1 Buen truco, gracias. – EM0

0

También puede utilizar:

EXECUTE 'COPY (SELECT ''progress: ' || progress_variable || ''') TO ''d:\progress.txt'''; 

dentro de su función para escribir el progreso actual en un archivo de texto.

Cuestiones relacionadas