Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Firebird e Interbase (https://www.clubdelphi.com/foros/forumdisplay.php?f=19)
-   -   Tarda mucho en ejecutar un SP (https://www.clubdelphi.com/foros/showthread.php?t=69125)

Choclito 09-08-2010 17:08:20

Gracias por responder
 
Disculpen por responder tarde, probe lo que dice el amigo guillotmarc y el IB plananalyzer me dice que las tres tablas estan indexadas, ahora probare con el resto de mis consultas .
Sobre la condicion del where es lo mismo
(r.fecha between :f1 and :f2 + 1 and r.fecha <> :f2 + 1) por esto (cast(r.fecha as date) between :f1 and :f2) se tiene que sumar siempre mas 1 osea f2+1 ??
Solo quisiera una explicacion asi de ese modo me evito de utilizar la funcion cast .
Yo lo realizaba porq el campo fecha es timestamp mientras en las consultas solo me importan de un rango de fechas determinado
Muchas gracias por la respuesta

Kipow 09-08-2010 18:48:11

El IB planalizer te debe de ayudar a determinar el plan que esta usando tu consulta y tu mismo debes de evaluar si es el correcto tomando en cuenta el numero de lecturas por tabla involucrada en la consulta. Por otro lado si utilizas cast estas dejando de utilizar el indice sobre el campo fecha si existiera. no veo porque no te funciona de la primera forma (fecha between :f1 and f2).

guillotmarc 10-08-2010 14:40:17

Cita:

Empezado por Choclito (Mensaje 372979)
Disculpen por responder tarde, probe lo que dice el amigo guillotmarc y el IB plananalyzer me dice que las tres tablas estan indexadas, ahora probare con el resto de mis consultas .
Sobre la condicion del where es lo mismo
(r.fecha between :f1 and :f2 + 1 and r.fecha <> :f2 + 1) por esto (cast(r.fecha as date) between :f1 and :f2) se tiene que sumar siempre mas 1 osea f2+1 ??
Solo quisiera una explicacion asi de ese modo me evito de utilizar la funcion cast .
Yo lo realizaba porq el campo fecha es timestamp mientras en las consultas solo me importan de un rango de fechas determinado
Muchas gracias por la respuesta


Que el IB plananlyzer te diga que se va a utilizar un índice no quiere decir que vaya a ir rápido obligatoriamente. Puesto que el motor puede utilizar algún índice disponible que acelere un poco la consulta (aunque por ejemplo bajar de 10 minutos a 4 minutos, normalmente no es de ninguna ayuda), y lo que necesitas es dar de alta un índice nuevo sobre un campo concreto, que es el que permitirá al motor acelerar de forma óptima la consulta y que se ejecute en algunos segundos. Así que no solo tienes que mirar que se utilice algún índice, también tienes que mirar que ese índice realmente sea óptimo para la consulta o bien si necesitas crear uno nuevo más adecuado.

Respecto a las consultas de fechas, el +1 hay que ponerlo dependiendo de lo que tengas guardado en la base de datos. El campo es de tipo timestamp, pero no sabemos si en tu programas guardas la parte de hora de las fechas o no lo haces.

Si guardas en la base de datos la parte de hora, entonces un registro que tenga guardado, por ejemplo, : 12-4-2010 17:25 no aparecerá en una consulta que sea BETWEEN 10-4-2010 y 12-4-2010, ya que 12-4-2010 17:25 es mayor que 12-4-2010 (si no pones nada, es a las 00:00).

Choclito 10-08-2010 15:19:58

gracias por las respuestas
 
Muchas gracias amigo guillotmarc y Kipow, respecto al campo fecha comentarles que guardo la fecha y hora mas por lo que el tendre que utilizar fecha+1.
Respecto a los indices comentarles que en el Sp que tengo llamo a varios select he estado probando por separado en el plan analyzer y e estado mejorando los tiempos de ejecucion , solo en el siguiente tengo problemas:
Código SQL [-]
select  r.nro_recibo,cast(r.fecha as date),d.ap_paterno||' '||d.ap_materno||' '||d.nombres||'-->'||e.nombre_e, case r.porcentaje_cobro when 100 then  c.costo else (r.porcentaje_cobro*c.costo)/100 end,r.costo_total,r.literal,r.nro_ambulatorio,r.usuario,r.tipo_paciente,r.nro_asegurado,r.nro_intern  acion,r.factura,cast(r.fecha as time),r.monto_cobrar,r.porcentaje_cobro,c.nro,r.nro_factura
from recibo r,registro_consulta_med c,c_externa c1,doctor d,especialidad e
where ((r.nro_recibo=c.nro_recibo)and(c.nro_consulta=c1.nro)and(c1.id_doctor=d.ci)and(d.esp=e.nro)and(cast  (r.fecha as date) between :f1 and :f2)and((r.cancelado=:valor)or(r.cancelado='M')))
el plan que me muestra es el siguiente:
PLAN JOIN (C1 NATURAL, D INDEX (PK_DOCTOR), E INDEX (PK_ESPECIALIDAD), C INDEX (REGISTRO_CONSULTA_MED_IDX4), R INDEX (PK_RECIBO))
Indicarles que en registro_consulta_med he creado un indice sobre el campo nro_consulta y aun eso no logro encontrar el error, pues el ibplan analyzer me muestra que esta tabla no esta indexada y en la grafica me muestra que la tabla c_externa no esta indexada, ademas el campo selectivity es de 80.80 para el indice REGISTRO_CONSULTA_MED_IDX4 del campo nro_consulta.
Comentarles que aparte de los indices creados por las llaves primarias y foraneas he creado nuevamente en las tablas indices sobre los campos que son llaves.
Y sobre como esta la consulta disculpen pues haciendo pruebas con el inner join me mostraba un mensaje en el alias de la tabla especialidad, como puedo estructurar mi consulta con inner join , creo q ahi esta tambien el problema.
Muchas gracias por responder y sus respuestas me ayudan mas a aprender sobre firebird

guillotmarc 10-08-2010 18:52:46

Hola. En efecto, lo primero que tienes que hacer es pasar la consulta a JOINS explícitos, la consulta de esta forma es todo un desafío para cualquier motor. Además que no entiendo porqué haces así las consultas de buen principio, resulta mucho más fácil y sencillo el construirlas con JOINS desde el inicio.
Código SQL [-]
select  r.nro_recibo,cast(r.fecha as date),d.ap_paterno||' '||d.ap_materno||' '||d.nombres||'-->'||e.nombre_e, case r.porcentaje_cobro when 100 then  c.costo else (r.porcentaje_cobro*c.costo)/100 end,r.costo_total,r.literal,r.nro_ambulatorio,r.usuario,r.tipo_paciente,r.nro_asegurado,r.nro_intern  acion,r.factura,cast(r.fecha as time),r.monto_cobrar,r.porcentaje_cobro,c.nro,r.nro_factura from recibo r,registro_consulta_med c,c_externa c1,doctor d,especialidad e where ((r.nro_recibo=c.nro_recibo)and(c.nro_consulta=c1.nro)and(c1.id_doctor=d.ci)and(d.esp=e.nro)and(cast  (r.fecha as date) between :f1 and :f2)and((r.cancelado=:valor)or(r.cancelado='M')))
Esta consulta es equivalente a :
Código SQL [-]
select  r.nro_recibo,cast(r.fecha as date),d.ap_paterno||' '||d.ap_materno||' '||d.nombres||'-->'||e.nombre_e, case r.porcentaje_cobro when 100 then  c.costo else (r.porcentaje_cobro*c.costo)/100 end,r.costo_total,r.literal,r.nro_ambulatorio,r.usuario,r.tipo_paciente,r.nro_asegurado,r.nro_intern  acion,r.factura,cast(r.fecha as time),r.monto_cobrar,r.porcentaje_cobro,c.nro,r.nro_factura from recibo r      inner join registro_consulta_med c on (r.nro_recibo=c.nro_recibo)      inner join c_externa c1 c.nro_consulta=c1.nro      inner join doctor d on c1.id_doctor=d.ci      inner join especialidad e on d.esp=e.nro where (r.fecha between :f1 and :f2 + 1) and (r.cancelado=:valor or r.cancelado='M')
En principio con un índice sobre el campo fecha de la tabla recibo vas a tener bastante para que esta consulta se ejecute rápido.

guillotmarc 10-08-2010 18:55:37

No sé que ocurre con los saltos de línea al contestar mensajes. Te pongo de nuevo la consulta bien estructurada:
Código SQL [-]
select  r.nro_recibo,cast(r.fecha as date),d.ap_paterno||' '||d.ap_materno||' '||d.nombres||'-->'||e.nombre_e, case r.porcentaje_cobro when 100 then  c.costo else (r.porcentaje_cobro*c.costo)/100 end,r.costo_total,r.literal,r.nro_ambulatorio,r.usuario,r.tipo_paciente,r.nro_asegurado,r.nro_intern  acion,r.factura,cast(r.fecha as time),r.monto_cobrar,r.porcentaje_cobro,c.nro,r.nro_factura from recibo r      inner join registro_consulta_med c on (r.nro_recibo=c.nro_recibo)      inner join c_externa c1 c.nro_consulta=c1.nro      inner join doctor d on c1.id_doctor=d.ci      inner join especialidad e on d.esp=e.nro where (r.fecha between :f1 and :f2 + 1) and (r.cancelado=:valor or r.cancelado='M')

guillotmarc 10-08-2010 18:58:59

No hay manera, en fin te dejo la consulta en una sola línea, y tienes que insertar saltos de linea antes del FROM, de los INNER JOIN y del WHERE.

Choclito 12-08-2010 18:44:00

gracias por la respuesta
 
Muchas gracias amigo guillotmarc, he estado probando con los select por separado en el ibplanalyzer y tengo problemas en los iguientes select:
Código SQL [-]
select  r.nro_recibo,cast(r.fecha as date),v.cantidad||'==>'||m.nombre_producto||'==>'||p.nombre, case r.porcentaje_cobro when 100 then  v.costo else (r.porcentaje_cobro*v.costo)/100 end,r.costo_total,r.literal,r.nro_ambulatorio,r.usuario,r.tipo_paciente,r.nro_asegurado,r.nro_intern  acion,r.factura,cast(r.fecha as time),r.monto_cobrar,r.porcentaje_cobro,v.nro,r.nro_factura
from  recibo r
    inner join venta_med v on v.nro_recibo=r.nro_recibo
    inner join  medicamento m on m.id_producto=v.id_medicamento
    inner join presentacion_med p on m.id_presentacion=p.id_presentacion
where ((r.fecha  between :f1 and :f2+1 and r.fecha<>:f2+1)and((r.cancelado=:valor)or(r.cancelado='M')))
ya tengo creado indices tanto por llaves primarias y foraneas y en el ibplananalizer en la pestaña de la grafica me muestra que las tres tablas estan indexadas pero en la pestaña PLAN analisys me muestra lo siguiente
PLAN JOIN (R INDEX (RECIBO_IDX1), V INDEX (VENTA_MED_IDX1), M INDEX (PK_MEDICAMENTO), P INDEX (PK_PRESENTACION_MED))

en el arbol que genera del JOIN en el detalle que genera del indice VENTA_MED_IDX1 en el campo selectivity me muestra el valor de 4.57, comentarles que VENTA_MED_IDX1 es un indice que he creado en la tabla venta_med sobre el campo nro_recibo, como puedo solucionarlo???
Comentarles que algo similar me pasa en el siguiente select:
Código SQL [-]
select  r.nro_recibo,cast(r.fecha as date),a.nombre_a, case r.porcentaje_cobro when 100 then  e.costo else (r.porcentaje_cobro*e.costo)/100 end,r.costo_total,r.literal,r.nro_ambulatorio,r.usuario,r.tipo_paciente,r.nro_asegurado,r.nro_intern  acion,r.factura,cast(r.fecha as time),r.monto_cobrar,r.porcentaje_cobro,e.nro,r.nro_factura
from recibo r
     inner join  registro_examenes_lab E on E.nro_recibo=r.nro_recibo
     inner join analisis_clinico A on  a.nombre_a=e.examen
where ((r.fecha between :f1 and :f2+1 and r.fecha<>:f2+1)and((r.cancelado=:valor)or(r.cancelado='M')))
Esta vez me muestra lo siguiente:
PLAN JOIN (R INDEX (RECIBO_IDX1), E INDEX (FK_REGISTRO_EXAMENES_LAB_2), A INDEX (PK_ANALISIS_CLINICO))
y el icono de exclamación me muestra sobre el indice FK_REGISTRO_EXAMENES_LAB_2 que es el indice sobre el campo nro_recibo de la tabla registro_examenes_lab
En los dos select la exclamacion esta sobre los indices creados sobre el campo nro_recibo, ya he creado nuevos indices sobre esos campos y el icono de exclamacion me muestra sobre los indices creados
Que es lo que tendria que cambiar ?? o porque en esos dos select en esos indices me muestra un valor mayor a 1 en el campo selectivity del ib plananalizer
Muchas gracias por sus comentarios y bueno solo decir que importante son los indices para agilizar consultas
Y disculpas por responder tardee

guillotmarc 13-08-2010 17:01:28

¿ Cuanto tarda en ejecutarse ?. ¿ Cuantas filas devuelve ?. ¿ El indice RECIBO_IDX1 sobre que campos es ? ¿ Cuantos registros tienes venta_med ? ¿ Cuantos registros tiene recibo ? ¿ Cuantos registros tiene medicamento ? ¿ Cuantos registros tiene presentacion_med ? ¿ Cuantos registros tiene registro_examenes_lab ? ¿ Cuantos registros tiene analisis_clinico ?

guillotmarc 13-08-2010 17:02:46

Por favor, arreglad los saltos de línea de los mensajes. En Firefox 3.6.4 sobre Windows 7, no coge ni un solo salto de línea.


La franja horaria es GMT +2. Ahora son las 13:08:59.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi