PDA

Ver la Versión Completa : Evaluar condiciones con Oracle PL/SQL


Tino
20-07-2004, 02:29:01
Tengo la tarea de evaluar una condición lógica del tipo:


('PLATÓN'='FILÓSOFO') OR (3 <> 5) AND NOT (2/3/2004 < 1/1/2005) ...


Para ello, he escrito la sig. rútina:


FUNCTION Fu_Evalua_Condicion(p_condicion IN VARCHAR2) RETURN BOOLEAN IS
-- Evalua la condición pasada como parámetro
vSQL VARCHAR2(300);
vDummy VARCHAR2(1);
BEGIN
vSQL := 'SELECT ''X'' FROM DUAL WHERE ' || p_condicion;
BEGIN
EXECUTE IMMEDIATE vSQL INTO vDummy;
If vDummy = 'X' Then
RETURN TRUE;
Else
RETURN FALSE;
End If;
EXCEPTION
WHEN OTHERS THEN RETURN FALSE;
END;
END Fu_Evalua_Condicion;



¿Cabe una mejor solución? El rendimiento es crítico porque esta rútina será llamada muchas veces, pero no se me ocurre otra manera.

Agradezco de antemano cualquier comentario que hagaís.

jachguate
20-07-2004, 03:09:00
Queres saber si la condición es válida, o si es verdadera?

Que tanto son muchas veces?

Cuantas condiciones diferentes vas a evaluar de esta forma?

Hasta luego.

;)

Tino
20-07-2004, 08:17:33
La condición debe ser válida aunque pudiera no serlo. Si la condición no es válida se evaluará como falsa.

A esta función se le llama por cada registro leído de la tabla principal, o sea, un montón de veces.

La condición a evaluar puede ser cualquiera que se pueda poner en la parte WHERE de una consulta SQL.

Saludos.

jachguate
20-07-2004, 18:11:31
No me imagino como para que necesitas esto... pero el método concebido es bastante ingenioso y funcional, aunque ciertamente no es óptimo.

Si las condiciones no son muy variadas... sería mucho mejor trabajar con consultas parámetrizadas, de manera que se pueda aprovechar el cache y no obligar a reanalizar la consulta cada vez que se envía.

Dependiendo de la versión de Oracle que uses, puede ser aconsejable también no usar la tabla dual para hacer la consulta.. pues es bastante ineficiente, ya que por alguna razón el motor no la mantiene en memoria y obliga a dos acceso al disco por cada consulta. Es mejor crear tu propia tabla (xDual) que tenga un solo registro (podes garantizarlo con la PK) y basarte en esta, que si se mantendrá en cache para hacer las consultas.

Con esas dos mejoras... será mucho mas eficiente.

Hasta luego.

;)

Tino
20-07-2004, 21:59:02
De verdad, gracias jachguate por tus consejos, aunque creo que no podré aplicarlos porque la condición a evaluar (que puede ser múltiple) no veo la manera de parametrizarla. Es demasiado variable, y no sabríamos ni siquiera el nro. de parámetros a usar. Necesitaria preprocesar la condición para saber el nro. (y tipo) de los parámetros y eso no resultaría eficiente.

Apuntaré tu comentario sobre la shared pool acerca de la tabla dual. De todos modos crear una tabla unicamente para este propósito... no sé. Supongo que haré pruebas, como siempre, antes de decidirme. No estoy seguro tampoco de que de esta manera aproveche la cache pues tengo entendido de que la optimización se consigue cuando la consulta a analizar por el motor es identica a la almacenada en la cache y dada la disparidad de consultas SQL que va a lanzar mi rútina no creo que se logre aprovechar en alguna manera de la cache. Por tus comentarios y por los de delphi.com.ar (en otro hilo) he aprendido que el uso de parámetros facilita la entrada de la consulta en la caché , algo que no sabía y que puede serme muy útil. Si sabeís de algo sobre la shared pool adicional os agradecería que lo comentaraís.

¿El motivo de esta rútina? Por si tienes curiosidad: imagina una relación maestro detalle con dos tablas 1:N. Bien, necesitamos recuperar por cada registro de la tabla maestra un único (o ninguno, pero no más) registro de la tabla detalle. Y este único registro es el único cuya condición (que se guarda en un campo) se cumple. Necesitamos un cursor que recorre los registros de la tabla detalle y que vaya evaluando sus condiciones hasta encontrar el que se cumple.

Saludos y gracias por la ayuda.

jachguate
20-07-2004, 23:01:56
Apuntaré tu comentario sobre la shared pool acerca de la tabla dual. De todos modos crear una tabla unicamente para este propósito... no sé. Supongo que haré pruebas, como siempre, antes de decidirme. No estoy seguro tampoco de que de esta manera aproveche la cache pues tengo entendido de que la optimización se consigue cuando la consulta a analizar por el motor es identica a la almacenada
En este caso no me referia a la shared pool, sino a la Database Buffer Cache, también del SGA, que es el otro punto a optimizar, y que la tabla DUAL no aprovecha (según leí en algun artículo que busque pero no logré encontrar).

Si sabeís de algo sobre la shared pool adicional os agradecería que lo comentaraís.
Te recomiendo la lectura del capítulo 1 (Introduction to the Oracle Server) del manual Database Concepts de tu versión. También una lectura al Administrator's Guide y Performance Tuning Guide and Reference no te vendria nada mal.

Hasta luego.

;)