PDA

Ver la Versión Completa : Select a procedimiento almacenado


ACK
15-07-2003, 11:43:46
Hola Foristas!!!

Tengo un problemilla.

Tengo un stored procedure para realizar una consulta bastante complicada, al cual le paso unos parametros para que me acote el resultado.

Cuando le hago un select, sin incluir ningun tipo de where en la consulta, funciona bien, las consultas van por lo indices y va todo estupendo, el problema lo tengo cuando a dicho select, le añado la clausula where con alguna condicion por alguno de los campos que me devuelve la consulta. Resulta que me tarda unas 10 veces mas que la original.

Para que quede mas claro :

Esto va estupendo :
select cons.*
from Procedimiento ( parametro1, parametro2 );

Esto tarda 10 veces mas :
select cons.*
from Procedimiento ( parametro1, parametro2 )
where cons.columna=dato;


¿Alguien puede orientarme un poco para ver como puedo resolver esto?

¿Tiene algo que ver con el motor de interbase?

Gracias a todos por adelantado.

guillotmarc
15-07-2003, 13:08:41
Hola.

¿ Porque no añades un parámetro más al procedimiento almacenado, y haces el where dentro de él ?.

De esta forma, la consulta quedará optimizada dentro del código del procedimiento almacenado.

Saludos.

ACK
15-07-2003, 15:36:32
El problema es que el procedimiento almacenado devuelve unas 30 columnas. Se pasan como parametros las consultas mas frecuentes(las que se utilizan diariamente), y, mediante otra opción se construye el where del select con las consultas menos frecuentes, las cuales dependen de los resultados obtenidos de dicha consulta.

Por eso, esa opción la descarté en su momento.

guillotmarc
16-07-2003, 21:27:33
Hola.

No conozco ninguna forma de optimizarlo de la forma que quieres, y como creo que la consulta se optimizaría correctamente con otro parámetro (optativo) en el procedimiento, quizá te interese ver la propuesta que hago en esta discusión :

http://www.clubdelphi.com/foros/showthread.php?s=&postid=8985#post8985

Saludos.

Kafu
17-07-2003, 14:27:52
Yo consideraría seriamente la propuesta de GuillotMarc aunque te resulte un poco costosa, porque el problema tiene la pinta de que se evalúa el procedimiento almacenado una vez por cada fila que devolviera si no pusieras la condición where.
Esto es, no trae todos los registros del SP y después los evalúa a ver cual cumple la condición, sino que va llamando al sp cada vez, mira la fila a ver si cumple la condición y vuleve a buscar la siguiente.
No utilizo SP y es posible que esté metiendo la pata hasta la ingle, pero es altamente sospechoso, a mí me ha pasado algo parecido en querys normales en los que usaba el
WHERE TAL NOT IN (SELECT...).
Un saludo,

F.T.G.

kinobi
17-07-2003, 15:28:49
Hola,

Posteado originalmente por Kafu

Esto es, no trae todos los registros del SP y después los evalúa a ver cual cumple la condición, sino que va llamando al sp cada vez, mira la fila a ver si cumple la condición y vuleve a buscar la siguiente.

yo opino lo contrario. Creo que la consulta se resuelve enteramente en el lado servidor (con la correspondiente llamada al procedimiento y la posterior selección de la cláusula WHERE) y se envía posteriormente el resultado, ya filtrado, al cliente.

Sí coincido con la idea de que añadir la cláusula WHERE en el procedimiento, pasando los parámetros oportunos, puede mejorar el rendimiento de la consulta.

Saludos.

Angel
17-07-2003, 17:13:59
No sé si tienes un índice sobre esa columna sobre la que haces el where, pero si no, ¿has probado a ponerle un índice?

guillotmarc
17-07-2003, 18:45:33
Hola.

Posteado originalmente por kinobi
yo opino lo contrario. Creo que la consulta se resuelve enteramente en el lado servidor (con la correspondiente llamada al procedimiento y la posterior selección de la cláusula WHERE) y se envía posteriormente el resultado, ya filtrado, al cliente.


Creo que Kafu no se refería a que parte del resultado se construya en el cliente, sinó a como gestiona internamente el motor de Interbase la consulta.

Es decir, que supone que Interbase para construir el resultado va lanzando n veces la consulta, evaluando para cada una de ellas el parámetro. (Como si fuera una subconsulta correlacionada).

Una vez evaluado el resultado correcto lo devuelve al cliente. Todo el proceso ha corrido en el Servidor, pero como el motor ha ejecutado varias veces el procedimiento almacenado, por eso la consulta tarda tanto.

Saludos.

kinobi
17-07-2003, 19:03:42
Hola,

Posteado originalmente por guillotmarc
Es decir, que supone que Interbase para construir el resultado va lanzando n veces la consulta, evaluando para cada una de ellas el parámetro. (Como si fuera una subconsulta correlacionada).

entendido. De todas formas tengo la impresión (habría que comprobarlo en los fuentes) que no es necesario lanzar n veces la consulta. En mi opinión, en la ejecución del procedimiento, al estar dentro de una Select, se va construyendo un cursor (alimentado seguramente por cada SUSPEND del procedimiento). Cada vez que el procedimiento devuelve una nueva fila, y antes de introducirla en el cursor que se devolverá al cliente, se decide si ha de formar parte del mismo (por medio de la cláusula WHERE). Otra cosa sería que la llamada estuviera dentro de otra Select como tu comentas.

Saludos.

mlara
18-07-2003, 00:29:08
Yo pienso, tal como dice Juan R. que no es lógico que el SP se ejecute varias veces, una por cada fila que se deba retornar de acuerdo a la condición en la cláusula WHERE.

Veamos:

Si escribo: SELECT * FROM SP_NAME;

, como se supone hay al menos un SUSPEND dentro del SP, de hecho el SP se "suspende" cuando retorna la primera fila, pero dado que no hay cláusula WHERE entonces estamos seleccionando todas las filas, y para poderse mostrar la siguiente.. y luego la siguiente, por cada fila adicional la ejecución del SP "continúa", pero No se ejecuta de nuevo.

Por otro lado, la "continuación" de la ejecución del SP debe ser completamente independiente de que exista o no una cláusula WHERE en la sentencia SELECT que lo llama.

De otra manera, no es lógico, que por el hecho de haber una clásula WHERE se deba ejecutar de nuevo el procedimiento y al tiempo el mismo retorne la n-ésima fila. Eso no tiene sentido.

Yo opino que en definitiva, lo que sucede en este caso es algo "EXTRAÑO" mientras no se compruebe lo contrario.

Tal vez ACK pueda decírnoslo cuando lo averigue.

De todas formas, yo tengo una duda al respecto de la forma en que se hace la consulta:

¿por qué se escribe 'cons.*' y luego 'cons.columna', en vez de '*' y luego solamente 'columna'?

ACK
18-07-2003, 08:53:14
Perdón ha sido un pequeño error al escribir, la consulta original tenia algún que otro join, y al intentar simplificarla, arrastré algunas cosillas innecesarias, pero esto no afecta al problema en cuestión :

select *
from Procedimiento ( parametro1, parametro2 )
where columna=dato;

Veo que la pregunta está dando mucho de sí, lo cual es bueno, por que, al final, todos terminaremos aprendiendo algo nuevo.

Yo, de momento, sigo haciendo pruebas. No he llegado a encontrar ninguna solucion, pero, contestando a la pregunta de Angel, de si tengo un indice por esa columna, la respuesta es si.
He hecho pruebas con columnas en las que tengo un indice, y por columnas en las que no lo tengo, y el resultado es igual de desastroso (tarda mas de 20 veces que la consulta sin where).

Gracias por vuestra colaboración.

Iván
18-07-2003, 10:01:45
Creo que por mucho que tengas un indice no sirve de nada al hacer la consulta sobre un SP, ya que no la haces directamente sobre la tabla, sino que lo haces sobre un conjunto de datos resultado de la consulta del SP.

Por otra parte, creo q no vas a conseguir nunca la misma eficiencia haciendo un select de un SP con una clausula Where, como si pusieras la condicion Where dentro del SP.

Otra posibilidad, si el conjunto de datos resultado no es muy grande, sería traerte todos los datos al cliente y filtrarlos una vez lo tienes allí.

Saludos.

mlara
19-07-2003, 20:13:28
Hay varias soluciones alternas, como por ejemplo, hacer que el SP guarde sus resultados en una tabla de resultados, creada exclusivamente para ese propósito, para luego hacer un SELECT de esa tabla. Sin embargo, yo pienso que eso tampoco es lógico, pero seguramente serviría para acelerar la obtención de los resultados deseados.