sql >> Base de Datos >  >> RDS >> Oracle

Procedimiento almacenado de Oracle, devolviendo el cursor de referencia frente a las matrices asociativas

La solicitud del DBA no tiene sentido.

Lo que el DBA seguramente está pensando es que quiere minimizar la cantidad de cambios de contexto del motor SQL a PL/SQL que ocurren cuando obtiene datos de un cursor. Pero la solución que se sugiere está mal dirigida a este problema en particular e introduce otros problemas de rendimiento mucho más serios en la mayoría de los sistemas.

En Oracle, se produce un cambio de contexto de SQL a PL/SQL cuando la VM de PL/SQL solicita más datos a la VM de SQL, la VM de SQL responde ejecutando más la instrucción para obtener los datos que luego empaqueta y devuelve al PL. /máquina virtual SQL. Si el motor PL/SQL solicita filas de una en una y usted obtiene muchas filas, es posible que estos cambios de contexto representen una fracción significativa de su tiempo de ejecución general. Para combatir ese problema, Oracle introdujo el concepto de operaciones masivas al menos en los días 8i. Esto permitió que la máquina virtual PL/SQL solicitara varias filas a la vez desde la máquina virtual SQL. Si la máquina virtual PL/SQL solicita 100 filas a la vez, habrá eliminado el 99 % de los cambios de contexto y su código potencialmente se ejecutará mucho más rápido.

Una vez que se introdujeron las operaciones masivas, hubo una gran cantidad de código que podría refactorizarse para ser más eficiente mediante el uso explícito de BULK COLLECT operaciones en lugar de obtener fila por fila y luego usar FORALL bucles para procesar los datos en esas colecciones. Sin embargo, para los 10,2 días, Oracle había integrado operaciones masivas en FOR implícito bucles por lo que un implícito FOR loop ahora realiza automáticamente recopilaciones masivas en lotes de 100 en lugar de buscar fila por fila.

Sin embargo, en su caso, dado que está devolviendo los datos a una aplicación cliente, el uso de operaciones masivas es mucho menos significativo. Cualquier API del lado del cliente decente tendrá una funcionalidad que le permita al cliente especificar cuántas filas deben recuperarse del cursor en cada red ida y vuelta y esas solicitudes de recuperación irán directamente a la VM de SQL, no a través del PL. /SQL VM, por lo que no hay que preocuparse por los cambios de contexto de SQL a PL/SQL. Su aplicación debe preocuparse por obtener una cantidad adecuada de filas en cada viaje de ida y vuelta, lo suficiente como para que la aplicación no se vuelva demasiado habladora y se convierta en un cuello de botella en la red, pero no tantas como para tener que esperar demasiado para que los resultados sean devuelto o para almacenar demasiados datos en la memoria.

Devolver colecciones PL/SQL en lugar de un REF CURSOR a una aplicación cliente no reducirá la cantidad de cambios de contexto que se producen. Pero va a tener un montón de otras desventajas, una de las cuales es el uso de memoria. Una colección PL/SQL debe almacenarse completamente en el área global de proceso (PGA) (suponiendo conexiones de servidor dedicadas) en el servidor de la base de datos. Esta es una parte de la memoria que debe asignarse desde la RAM del servidor. Eso significa que el servidor tendrá que asignar memoria en la que buscar hasta la última fila que solicite cada cliente. Eso, a su vez, limitará drásticamente la escalabilidad de su aplicación y, dependiendo de la configuración de la base de datos, puede robar RAM de otras partes de la base de datos de Oracle que sería muy útil para mejorar el rendimiento de la aplicación. Y si se queda sin espacio PGA, sus sesiones comenzarán a tener errores relacionados con la memoria. Incluso en aplicaciones puramente basadas en PL/SQL, nunca querrá obtener todos los datos en colecciones, siempre querrá obtenerlos en lotes más pequeños, para minimizar la cantidad de PGA que está utilizando.

Además, recuperar todos los datos en la memoria hará que la aplicación se sienta mucho más lenta. Casi cualquier marco le permitirá obtener datos a medida que los necesite, por ejemplo, si tiene un informe que muestra en páginas de 25 filas cada una, su aplicación solo necesitará obtener las primeras 25 filas antes de pintar el primera pantalla. Y nunca tendría que buscar las siguientes 25 filas a menos que el usuario solicitara la siguiente página de resultados. Sin embargo, si está obteniendo los datos en matrices como propone su DBA, tendrá que obtener todas las filas antes de que su aplicación pueda comenzar a mostrar la primera fila, incluso si el usuario nunca quiere ver más que el primer puñado de filas Eso significará muchas más E/S en el servidor de la base de datos para obtener todas las filas, más PGA en el servidor, más RAM en el servidor de aplicaciones para almacenar el resultado en búfer y más tiempo de espera para la red.