Compartir a través de


Usar el almacenamiento en búfer adaptable

El almacenamiento en búfer adaptable se usa desde la versión 1.2 del controlador JDBC de Microsoft SQL Server 2005, que se ha diseñado para recuperar cualquier tipo de datos de valores grandes sin sufrir la sobrecarga de los cursores de servidor. La aplicaciones pueden usar la característica de almacenamiento en búfer adaptable con todas las versiones de SQL Server que son compatibles con el controlador.

Normalmente, cuando el controlador JDBC de Microsoft SQL Server ejecuta una consulta, lleva todos los resultados del servidor a la memoria de la aplicación. Aunque este enfoque reduce el uso de recursos en SQL Server, puede iniciar una OutOfMemoryError en la aplicación JDBC para las consultas que producen resultados muy grandes.

Para permitir que las aplicaciones administren los resultados muy grandes, el controlador JDBC de Microsoft SQL Server proporciona el almacenamiento en búfer adaptable. Con el almacenamiento en búfer adaptable, el controlador JDBC recupera los resultados de la ejecución de una instrucción de SQL Server a medida que la aplicación los necesita, en lugar de todos a la vez. El controlador también descarta los resultados en cuanto la aplicación ya no puede tener acceso a ellos. Se incluyen a continuación algunos ejemplos en los que el almacenamiento en búfer adaptable puede ser útil:

  • La consulta genera un conjunto de resultados muy grande: la aplicación puede ejecutar una instrucción SELECT que genera más filas de las que la aplicación puede almacenar en memoria. En las versiones anteriores, la aplicación tenía que utilizar un cursor de servidor para evitar un OutOfMemoryError. El almacenamiento en búfer adaptable permite hacer un paso de solo lectura y solo avance de un conjunto de resultados arbitrariamente grande sin requerir un cursor de servidor.

  • La consulta genera columnas de SQLServerResultSet muy grandes o valores de parámetros SQLServerCallableStatement OUT: la aplicación puede recuperar un valor único (columna o el parámetro OUT) que es demasiado grande como para que quepa completamente en la memoria de la aplicación. El almacenamiento en búfer adaptable permite a la aplicación cliente recuperar este valor como una secuencia, utilizando los métodos getAsciiStream, getBinaryStream, o getCharacterStream. La aplicación recupera el valor de SQL Server cuando lee de la secuencia.

Nota

Con el almacenamiento en búfer adaptable, el controlador JDBC solamente almacena en búfer las cantidad de datos que debe almacenar. El controlador no proporciona un método público para controlar o limitar el tamaño del búfer.

Establecer el almacenamiento en búfer adaptable

Desde la versión 2.0 del controlador JDBC, el comportamiento predeterminado del controlador es "adaptive". Dicho de otro modo, para obtener el comportamiento de almacenamiento en búfer adaptable, su aplicación no tiene que solicitar explícitamente el comportamiento adaptable. En la versión 1.2, sin embargo, el modo del almacenamiento en búfer era "full" de manera predeterminada y la aplicación tenía que solicitar el modo de almacenamiento en búfer adaptable explícitamente.

Hay tres formas en las que una aplicación puede solicitar que la ejecución de una instrucción deba usar el almacenamiento en búfer adaptable:

Al usar la versión 1.2 del controlador JDBC, la aplicación debe convertir el objeto de la instrucción en una clase SQLServerStatement para utilizar el método setResponseBuffering. Los ejemplos de código de Leer un ejemplo de datos grandes y de Leer datos grandes con un ejemplo de procedimientos almacenados muestran el uso antiguo.

Sin embargo, con la versión 2.0 del controlador JDBC, las aplicaciones pueden usar el método isWrapperFor y el método unwrap para obtener acceso a la funcionalidad específica del proveedor sin ninguna suposición sobre la jerarquía de clases de la implementación. Como código de ejemplo, vea el tema Actualizar un ejemplo de datos grandes.

Recuperar datos grandes con el almacenamiento en búfer adaptable

Cuando se leen valores grandes una vez con los métodos get<Type>Stream y se tiene acceso a las columnas ResultSet y a los parámetros OUT CallableStatement en el orden que devuelve SQL Server, el almacenamiento en búfer adaptable reduce la utilización de memoria de la aplicación al procesar los resultados. Al utilizar el almacenamiento en búfer adaptable:

  • Los métodos get<Type>Stream definidos en las clases SQLServerResultSet y SQLServerCallableStatement devuelven secuencias de una sola lectura de forma predeterminada, aunque se pueden restablecer las secuencias si lo determina la aplicación. Si la aplicación desea reset la secuencia, tiene que llamar primero al método mark en esa secuencia.

  • Los métodos get<Type>Stream definidos en las clases SQLServerClob y SQLServerBlob devuelven secuencias cuya posición siempre se puede cambiar a la inicial de la secuencia sin llamar al método mark.

Cuando la aplicación utiliza el almacenamiento en búfer adaptable, los valores recuperados por los métodos get<Type>Stream sólo se pueden recuperar una vez. Si intenta llamar a cualquier método get<Type> en la misma columna o parámetro después de llamar al método get<Type>Stream del mismo objeto, se produce una excepción con un mensaje similar a "Se obtuvo acceso a los datos y estos no están disponibles para esta columna o parámetro".

Directrices para el uso del almacenamiento en búfer adaptable

Los desarrolladores de software deberían seguir estas importantes directrices para disminuir la utilización de memoria por parte de la aplicación:

  • Evite utilizar la propiedad de cadena de conexión selectMethod=cursor para permitir a la aplicación procesar un conjunto de resultados muy grande. Desde la versión 1.2 del controlador JDBC de Microsoft SQL Server 2005, la característica de almacenamiento en búfer adaptable permite a las aplicaciones procesar los conjuntos de resultados de solo avance y solo lectura muy grandes sin utilizar un cursor de servidor. Tenga en cuenta que cuando configura selectMethod=cursor, se ven impactados todos los conjuntos de resultados de solo avance y solo lectura producidos por esa conexión. Dicho de otro modo, si su aplicación procesa rutinariamente conjuntos de resultados cortos con pocas filas, crear, leer y cerrar un cursor de servidor por cada conjunto de resultados usará más recursos en el lado cliente y en el lado servidor de lo que sucede cuando selectMethod no está configurado en cursor.

  • Lea los valores grandes de texto o binarios como secuencias mediante los métodos getAsciiStream, getBinaryStream, o getCharacterStream en lugar de los métodos getBlob o getClob. Desde la versión 1.2, la clase SQLServerCallableStatement proporciona métodos nuevos get<Type>Stream para este propósito.

  • Asegúrese de que las columnas con valores potencialmente grandes se colocan en último lugar en la lista de columnas en una instrucción SELECT y de que se usan los métodos get<Type>Stream de SQLServerResultSet para tener acceso a las columnas en el orden en que se seleccionan.

  • Asegúrese de que los parámetros OUT con valores potencialmente grandes se declaran en último lugar en la lista de parámetros del código SQL que se usa para crea la SQLServerCallableStatement. Además, compruebe que se usan los métodos get<Type>Stream de SQLServerCallableStatement para tener acceso a los parámetros OUT en el orden en que se declaran.

  • Evite ejecutar simultáneamente más de una instrucción en la misma conexión. Ejecutar otra instrucción antes de procesar los resultados de la anterior puede provocar que los resultados sin procesar se almacenen en el búfer en la memoria de la aplicación.

  • Hay algunos casos en los que usar selectMethod=cursor en lugar de responseBuffering=adaptive sería más beneficioso, como por ejemplo:

    • Si su aplicación procesa lentamente un conjunto de resultados de solo avance y solo lectura, como la lectura de cada fila después de alguna entrada del usuario, utilizar selectMethod=cursor en lugar deresponseBuffering=adaptive puede ayudar a reducir el uso de recursos por SQL Server.

    • Si su aplicación procesa dos o más conjuntos de resultados de solo avance y solo lectura al mismo tiempo en la misma conexión, utilizar selectMethod=cursor en lugar de responseBuffering=adaptive podría ayudar a reducir la memoria necesaria para el controlador mientras procesa estos conjuntos de resultados.

    En ambos casos, necesita considerar la sobrecarga de crear, leer y cerrar los cursores de servidor.

Además, la siguiente lista proporciona algunas recomendaciones para los conjuntos de resultados desplazables y actualizables de solo avance:

  • Para los conjuntos de resultados desplazables, cuando recupera un conjunto de filas el controlador siempre lee en la memoria el número de filas indicado por el método getFetchSize del objeto SQLServerResultSet, incluso aunque esté habilitado el almacenamiento en búfer adaptable. Si el desplazamiento produce un OutOfMemoryError, puede reducir el número de filas recuperadas llamando al método setFetchSize del objeto SQLServerResultSet para configurar el tamaño de recuperación en un número de filas más pequeño, incluso una sola fila si es necesario. Si esto no impide un OutOfMemoryError, , evite incluir columnas muy grandes en los conjuntos de resultados desplazables.

  • Para los conjuntos de resultados de solo avance, cuando recupera un conjunto de filas el controlador normalmente lee en la memoria el número de filas indicado por el método getFetchSize del objeto SQLServerResultSet, incluso aunque el almacenamiento en búfer adaptable esté habilitado en la conexión. Si la llamada al método next del objeto SQLServerResultSet produce un OutOfMemoryError, puede reducir el número de filas recuperadas llamando al método setFetchSize del objeto SQLServerResultSet para configurar el tamaño de recuperación en un número de filas más pequeño, incluso una sola fila si es necesario. También puede forzar el controlador para que no almacene filas en el almacenamiento den búfer llamando al método setResponseBuffering del objeto SQLServerStatement con el parámetro "adaptive" antes de ejecutar la instrucción. Como el conjunto de resultados no es desplazable, si la aplicación obtiene acceso a un número de columna grande utilizando uno de los métodos get<Type>Stream, el controlador rechaza el valor en cuanto la aplicación lo lee, lo mismo que hace con los conjuntos de resultados de solo avance y solo lectura.

Vea también

Otros recursos

Mejorar el rendimiento y la confiabilidad con el controlador JDBC