2010-01-08 29 views
6

devuelve la consulta siguientes datos de inmediato:¿Por qué no postgresql comienza a devolver filas inmediatamente?

SELECT time, value from data order by time limit 100; 

Sin la cláusula de límite, se tarda mucho tiempo antes de que se inicie el servidor filas que regresan:

SELECT time, value from data order by time; 

observo esto, tanto mediante el uso de la herramienta de consulta (psql) y al consultar usando una API.

Preguntas/cuestiones:

  • la cantidad de trabajo que el servidor tiene que hacer antes de empezar a devolver filas debe ser el mismo para ambas sentencias de selección. ¿Correcto?
  • Si es así, ¿por qué hay un retraso en el caso 2?
  • ¿Hay algún problema de RDBMS fundamental que no entiendo?
  • ¿Hay alguna manera de que postgresql comience a devolver las filas de resultados al cliente sin pausa, también para el caso 2?
  • EDITAR (ver abajo). Parece que setFetchSize es la clave para resolver esto. En mi caso, ejecuto la consulta de python, usando SQLAlchemy. ¿Cómo puedo configurar esa opción para una sola consulta (ejecutada por session.execute)? Yo uso el controlador psycopg2.

La columna time es la clave principal, por cierto.

EDIT:

Creo que este extracto de la JDBC driver documentation describe el problema y consejos a una solución (todavía necesito ayuda - véase el último elemento de la lista de bala arriba):

Por defecto el controlador recopila todos los resultados de la consulta a la vez. Esto puede ser inconveniente para grandes conjuntos de datos, por lo que el controlador JDBC proporciona un medio para basar un ResultSet en un cursor de base de datos y solo recuperar un pequeño número de filas.

y

Cambio de código a modo de cursor es tan simple como establecer el tamaño de recuperación de la Declaración para el tamaño apropiado. Volver a establecer el tamaño de recuperación en 0 hará que todas las filas se guarden en caché (el comportamiento predeterminado).

// make sure autocommit is off 
conn.setAutoCommit(false); 
Statement st = conn.createStatement(); 

// Turn use of the cursor on. 
st.setFetchSize(50); 
+0

¿Qué driver estás usando? (probablemente psycopg2, pero confirme) –

+1

Usted se ayudó a sí mismo. ¡Bien hecho! –

+0

Sí, el controlador es psycopg2. – codeape

Respuesta

4

El controlador psycopg2 dbapi almacena el resultado completo de la consulta antes de devolver las filas. Tendrá que usar el cursor del lado del servidor para obtener resultados incrementalmente. Para SQLAlchemy, vea server_side_cursors in the docs y si está utilizando el ORM, Query.yield_per() method.

Actualmente, SQLAlchemy no tiene una opción para configurar esa consulta individual, pero there is a ticket with a patch for implementing that.

+0

Intenté usar un cursor del lado del servidor: c = conn.cursor ("mycursor"); c.execute ("..."); c.fetchmany (100). Pero aun así recibo una gran demora antes de que se devuelva algo. ¿Qué estoy haciendo mal? – codeape

+0

Asumir que conn es una conexión psycopg2, no tengo ni idea, funciona correctamente para mí. Puede intentar ejecutar EXPLAIN ANALYZE para la misma consulta y observar el primer número de la primera fila en el resultado de la explicación, que es el tiempo que le tomó a postgresql encontrar la primera fila. –

0

En teoría, debido a que su ORDER BY es por clave primaria, una especie de los resultados no debería ser necesario, y de hecho el PP podría devolver datos de inmediato en un orden clave.

Me gustaría contar con una base de datos capaz de darse cuenta de esto y optimizarlo. Parece que PGSQL no lo es. * encogerse de hombros *

No notará ningún impacto si tiene LIMIT 100 porque es muy rápido sacar esos 100 resultados de la base de datos, y no notará ninguna demora si primero se recogen y se ordenan antes de ser enviado a su cliente.

Sugiero tratar de dejar caer el ORDER BY. Lo más probable es que sus resultados estén correctamente ordenados por tiempo de todos modos (incluso puede haber un estándar o especificación que así lo requiera, dado su PK), y es posible que obtenga los resultados más rápidamente.

+0

Creo que es posible que haya leído mal mi pregunta. Con el LIMIT, la base de datos devuelve esas filas de inmediato. Sin el límite, hay una pausa antes de que se devuelvan las primeras filas al cliente. – codeape

+0

Las bases de datos pueden tener diferentes planes de consulta si el optimizador sabe que está interesado en los resultados lo más rápido posible. Oracle y DB2 tienen opciones para hacer eso. ¿Tal vez la cláusula límite patea la sugerencia de Postgresql de que la consulta quiere resultados de inmediato? –

+0

Sí, entendí mal su pregunta al principio, por eso lo renové todo. Por favor mira mi respuesta actualizada ahora! –

Cuestiones relacionadas