Pregunta

Estoy ejecutando una consulta en una tabla en una base de datos postgresql. La base de datos está en una máquina remota. La tabla tiene alrededor de 30 sub-tablas usando postgresql capacidad de partición .

La consulta devolverá un gran conjunto de resultados, alrededor de 1.8 millones de filas.

En mi código, utilizo el soporte spring jdbc, método JdbcTemplate.query , pero mi RowCallbackHandler no se está llamando.

Mi mejor suposición es que el controlador jdbc de postgresql (yo uso la versión 8.3-603.jdbc4) está acumulando el resultado en la memoria antes de llamar a mi código. Pensé que la configuración de fetchSize podría controlar esto, pero lo intenté y nada cambia. Hice esto como manual postgresql recomendado .

Esta consulta funcionó bien cuando usé Oracle XE. Pero estoy intentando migrar a postgresql debido a la función de partición, que no está disponible en Oracle XE.

Mi entorno:

  • Postgresql 8.3
  • Windows Server 2008 Enterprise de 64 bits
  • JRE 1.6 de 64 bits
  • Primavera 2.5.6
  • Controlador JDBC de Postgresql 8.3-603
¿Fue útil?

Solución

Para usar un cursor para recuperar datos, debe establecer el tipo de conjunto de resultados ResultSet.TYPE_FORWARD_ONLY (el valor predeterminado) y confirmar automáticamente en falso, además de configurar un tamaño de recuperación. Se hace referencia a eso en el documento al que se vinculó, pero no mencionó explícitamente que hizo esos pasos.

Tenga cuidado con el esquema de partición de PostgreSQL. Realmente hace cosas muy horribles con el optimizador y puede causar problemas de rendimiento masivos donde no debería haber (dependiendo de la información específica de sus datos). En cualquier caso, ¿su fila es solo 1.8M filas? No hay ninguna razón por la que deba particionarse según el tamaño solo, ya que está indexado adecuadamente.

Otros consejos

Estoy apostando a que no hay un solo cliente de su aplicación que necesite 1,8 millones de filas al mismo tiempo. Debería pensar en una forma sensata de dividir los resultados en partes más pequeñas y dar a los usuarios la oportunidad de recorrerlos.

Eso es lo que hace Google. Cuando haces una búsqueda, puede haber millones de visitas, pero devuelven 25 páginas a la vez con la idea de que encontrarás lo que buscas en la primera página.

Si no es un cliente, y los resultados están siendo masajeados de alguna manera, recomendaría dejar que la base de datos destruya todas esas filas y simplemente devuelva el resultado. No tiene sentido devolver 1.8M filas solo para hacer un cálculo en el nivel medio.

Si ninguno de los dos se aplica, tienes un problema real. Es hora de repensarlo.

Después de leer las respuestas posteriores, me parece que esto es más una solución de informes que debe procesarse por lotes o calcularse en tiempo real y almacenarse en tablas que no forman parte de su sistema transaccional. No hay forma de que se puedan escalar las filas de 1.8M al nivel medio para calcular los promedios móviles.

Recomiendo reorientarse, comience a pensar en ello como una solución de informes.

La propiedad fetchSize funcionó como se describe en manual de postgres .

Mi error fue que estaba configurando auto commit = false para una conexión de un grupo de conexiones que no era la conexión utilizada por la declaración preparada.

Gracias por todos los comentarios.

Hice todo lo anterior, pero necesitaba una última parte: asegúrese de que la llamada esté envuelta en una transacción y establezca la transacción en solo lectura, de modo que no se requiera un estado de reversión.

Agregué esto: @Transactional (readOnly = true)

Saludos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top