Ver Mensaje Individual
  #1 (permalink)  
Antiguo 10/05/2011, 04:58
Avatar de moNTeZIon
moNTeZIon
 
Fecha de Ingreso: enero-2005
Ubicación: Lliçà de Munt - BCN
Mensajes: 1.625
Antigüedad: 19 años, 4 meses
Puntos: 9
Novato: SQL tunning, índices... Necesito más velocidad en mi consulta

Buenos días.
Tengo una aplicación de control de tiempos, que ha estado funcionando en el cliente durante unos dos años.
La aplicación dispone de un informe que ofrece un listado de "incidencias detectadas".
Se trata de Tareas que han quedado abiertas en días anteriores, u otras incidencias que haya que corregir.
La consulta es una consulta de union que agrupa los diferentes tipos de incidencia, es la siguiente:
Código SQL:
Ver original
  1. SELECT A.Fecha AS Fecha,
  2. A.CodigoTrabajador AS CodigoTrabajador,
  3. T.Nombre AS NombreTrabajador,
  4. 'ASISTENCIA' AS TipoIncidencia,
  5. A.HoraInicio AS HoraInicio,
  6. 'No se ha cerrado la Asistencia' AS Descripcion
  7. FROM AsistenciasTrabajadores AS A
  8. INNER JOIN Trabajadores AS T ON A.CodigoTrabajador = T.CodigoTrabajador
  9. WHERE LEN(ISNULL(A.HoraFin, '')) = 0 AND A.Fecha<>@Fecha
  10.  
  11. UNION
  12.  
  13. SELECT P.Fecha AS Fecha,
  14. P.CodigoTrabajador AS CodigoTrabajador,
  15. T.Nombre AS NombreTrabajador,
  16. 'PARTE TRABAJO' AS TipoIncidencia,
  17. P.HoraInicio AS HoraInicio,
  18. 'No se ha cerrado el Parte | ' + L.CodigoOrdenProduccion + ' | ' + P.CodigoOperacion + ' - ' + L.NombreOperacion AS Descripcion
  19. FROM PartesTrabajo AS P
  20. INNER JOIN Trabajadores AS T ON P.CodigoTrabajador = T.CodigoTrabajador
  21. INNER JOIN LineasOrdenesProduccion AS L ON P.IdLineaOrdenProduccion = L.IdLineaOrdenProduccion
  22. WHERE LEN(ISNULL(P.HoraFin, '')) = 0 AND P.Fecha<>@Fecha
  23.  
  24. UNION
  25.  
  26. SELECT P.Fecha AS Fecha,
  27. P.CodigoTrabajador AS CodigoTrabajador,
  28. T.Nombre AS NombreTrabajador,
  29. 'PARTE TRABAJO' AS TipoIncidencia,
  30. P.HoraInicio AS HoraInicio,
  31. 'Parte cerrado fuera de tiempo | ' + L.CodigoOrdenProduccion + ' | ' + P.CodigoOperacion + ' - ' + L.NombreOperacion AS Descripcion
  32. FROM PartesTrabajo P
  33. INNER JOIN AsistenciasTrabajadores A ON P.CodigoTrabajador = A.CodigoTrabajador AND P.Fecha = A.Fecha
  34. INNER JOIN Trabajadores AS T ON P.CodigoTrabajador = T.CodigoTrabajador
  35. INNER JOIN LineasOrdenesProduccion AS L ON P.IdLineaOrdenProduccion = L.IdLineaOrdenProduccion
  36. WHERE CAST(P.HoraFin AS DateTime) NOT BETWEEN CAST(A.HoraInicio AS DateTime) AND CAST(A.HoraFin AS DateTime)
  37. AND CAST(P.HoraInicio AS DateTime) BETWEEN CAST(A.HoraInicio AS DateTime) AND CAST(A.HoraFin AS DateTime)
  38. AND CAST(P.HoraFin AS DateTime) > CAST(A.HoraFin AS DateTime)
  39. AND A.TipoAsistencia='A'
  40.  
  41. UNION
  42.  
  43. SELECT P.Fecha AS Fecha
  44. P.CodigoTrabajador AS CodigoTrabajador,
  45. T.Nombre AS NombreTrabajador,
  46. 'PARTE TRABAJO' AS TipoIncidencia,
  47. P.HoraInicio AS HoraInicio,
  48. 'Parte sin Asistencia | ' + L.CodigoOrdenProduccion + ' | ' + P.CodigoOperacion + ' - ' + L.NombreOperacion AS Descripcion
  49. FROM PartesTrabajo P
  50. INNER JOIN Trabajadores AS T ON P.CodigoTrabajador = T.CodigoTrabajador
  51. INNER JOIN LineasOrdenesProduccion AS L ON P.IdLineaOrdenProduccion = L.IdLineaOrdenProduccion
  52. LEFT JOIN AsistenciasTrabajadores A ON P.CodigoTrabajador = A.CodigoTrabajador AND P.Fecha = A.Fecha
  53. WHERE A.CodigoTrabajador IS NULL

El problema que me ocupa ahora, es que esta consulta ha comenzado a dar problemas de TimeOut.
Se que puedo aumentar el TimeOut a través del objeto SQLCommand de .NET que lanza la consulta.
Pero también he leído distintas opiniones que no aconsejan aumentar ese TimeOut, puesto que es mejor intentar "tunear" la consulta, aplicar índices, etc...
El motivo de este post es que, una vez revisada la consulta, puedan recomendarme las distintas acciones que crean convenientes.
Por ejemplo, tengo Primary Keys asignadas en cada tabla (lógicamente), y Foreign Keys, pero no existen otros índices.
Este es un resumen de las ForeignKeys:
Código SQL:
Ver original
  1. LineasOrdenesProduccion > FOREIGN KEY [CodigoOrdenProduccion] REFERENCES OrdenesProduccion ([CodigoOrdenProduccion])
  2. LineasOrdenesProduccion > FOREIGN KEY [CodigoOperacion] REFERENCES Operaciones ([CodigoOperacion])
  3. PartesTrabajo > FOREIGN KEY [CodigoTrabajador] REFERENCES Trabajadores ([CodigoTrabajador])
  4. PartesTrabajo > FOREIGN KEY [IdLineaOrdenProduccion] REFERENCES LineasOrdenesProduccion ([IdLineaOrdenProduccion])
  5. AsistenciasTrabajadores > FOREIGN KEY [CodigoTrabajador] REFERENCES Trabajadores ([CodigoTrabajador])

No sé qué tan importantes serán los nuevos índices que me recomienden en la velocidad de esta consulta, pero les estaría muy agradecido si me dieran sus opiniones al respecto.
Qué indices ven más convenientes, cambios en la consulta, u otros aspectos que no esté teniendo en cuenta.
Gracias por su ayuda.
Saludos.
__________________
..:: moNTeZIon ::..

Última edición por moNTeZIon; 10/05/2011 a las 05:11