none
Consulta SQL RRS feed

  • Pregunta

  • Hola, tengo que realizar un reporte con tres tablas, Usuarios, Empresa y Log, el reporte debe de mostrar a los usuarios, la empresa a la que pertenecen, si está activo o no y la última vez que accedieron a la intranet.

    Hasta el momento tengo la siguiente consulta:

    SELECT ent_mstr.ent_name AS Empresa, 
    		usr_mstr.usr_alias AS Nombre,
    		log_hist.log_date AS FecUltAcc,
    		usr_mstr.usr_isvalid AS Estatus
    	FROM usr_mstr
    		 LEFT JOIN ent_mstr ON usr_mstr.usr_ent_index = ent_mstr.ent_index
    		 LEFT JOIN log_hist ON ent_mstr.ent_index = log_hist.log_ent_index
    	WHERE usr_mstr.usr_isValid = 1

    Pero se tarda mucho, ya que el log tiene demasiados registros y no se me ocurre cómo optimizarla.




    lunes, 5 de marzo de 2018 16:55

Respuestas

  • Hola Sandra:

    Y porque no cambias la tabla AS log_Date

    por

    (SELECT MAX(l.LOG_DATE), l.LOG_USR_ALIAS FROM LOG_HIST as l GROUP BY l.LOG_USR_ALIAS) AS LOG_DATE

    De manera que obtienes la ultima fecha para cada usuario....

    Otra anotación aparte, no se te hace muy dificil leer las consultas. Si estableces un alias cortito, se leen mejor, creo.

    SELECT e.ent_name AS Empresa, 
    		e.usr_alias AS Nombre,
    		lg.log_date AS FecUltAcc,
    		u.usr_isvalid AS Estatus
    	FROM usr_mstr as u
    		 JOIN ent_mstr  as e ON u.usr_ent_index = e.ent_index
    		 JOIN (SELECT l.log_date, l.log_usr_alias 
    					FROM log_hist as l ) AS lg 
    		 ON lg.log_usr_alias = u.usr_alias
    	WHERE u.usr_isValid = 1
    	ORDER BY log_date DESC

    Ojo a lo mejor me cole con la sintaxis porque yo no tengo tus tablas.... pero creo que se lee más fácil.

    Un saludo

    lunes, 5 de marzo de 2018 20:27

Todas las respuestas

  • Esa parte de "si está activo o no" no parece estar reflejada en la consulta que usted muestra puesto que parece que el WHERE contiene una cláusula para incluir solamente usuarios activos.

    No hay más condiciones en el WHERE que pudieran ayudar a reducir el tiempo de la consulta.  Esto nos lleva a cuestionarnos la parte de unión.  La única manera de mejorar el tiempo sería si log_hist.log_ent_index no tuviera un índice.  ¿Lo tiene?  Yo imaginaría que sí, pero verifique usted.


    Jose R. MCP
    Code Samples

    lunes, 5 de marzo de 2018 17:08
  • Sí, en el where busco sólo usuarios activos y en efecto la tabla de Log tiene un índice. Me comentaron que podría hacerse con una subconsulta para optimizar el tiempo pero no se me ocurre en dónde ponerla.
    lunes, 5 de marzo de 2018 17:16
  • Eso es tan vago e inexacto como decir "puede usarse un índice para optimizar", y no especificar un índice sobre qué columnas y de cuál tabla.

    No veo ninguna lógica detrás de la dichosa "subconsulta".  Si esta persona que se la recomendó pudiera elaborar al respecto sería genial.

    Como le dije antes:  La optimización de una consulta se da alrededor de las condiciones de la consulta (los WHERE y los ON) la mayoría de los casos.  Podría haber otros problemas de desempeño como acceso lento al disco duro, pero entonces ya hablamos de optimizar el servidor en sí, agregando, por ejemplo, memoria RAM para que SQL Server sea capaz de tener la base de datos completa en RAM y por lo tanto ser, unas 1000 veces más rápido.


    Jose R. MCP
    Code Samples

    lunes, 5 de marzo de 2018 17:25
  • El log_ent_index es un índice de la tabla Empresa, la modifiqué un poco y el tiempo de respuesta es de 50 segundos.
    SELECT ent_mstr.ent_name AS Empresa, 
    		usr_mstr.usr_alias AS Nombre,
    		log_date.log_date AS FecUltAcc,
    		usr_mstr.usr_isvalid AS Estatus
    	FROM usr_mstr
    		 JOIN ent_mstr ON usr_mstr.usr_ent_index = ent_mstr.ent_index
    		 JOIN (SELECT log_hist.log_date, log_hist.log_usr_alias 
    					FROM log_hist ) AS log_date 
    		 ON log_date.log_usr_alias = usr_mstr.usr_alias
    	WHERE usr_mstr.usr_isValid = 1
    	ORDER BY log_date DESC
    Pero sigue siendo bastante tiempo
    lunes, 5 de marzo de 2018 18:42
  • Manda la consulta al servicio de TUNING y que te diga si necesitas indices o algun estadistico
    lunes, 5 de marzo de 2018 18:56
  • Hola Sandra:

    Y porque no cambias la tabla AS log_Date

    por

    (SELECT MAX(l.LOG_DATE), l.LOG_USR_ALIAS FROM LOG_HIST as l GROUP BY l.LOG_USR_ALIAS) AS LOG_DATE

    De manera que obtienes la ultima fecha para cada usuario....

    Otra anotación aparte, no se te hace muy dificil leer las consultas. Si estableces un alias cortito, se leen mejor, creo.

    SELECT e.ent_name AS Empresa, 
    		e.usr_alias AS Nombre,
    		lg.log_date AS FecUltAcc,
    		u.usr_isvalid AS Estatus
    	FROM usr_mstr as u
    		 JOIN ent_mstr  as e ON u.usr_ent_index = e.ent_index
    		 JOIN (SELECT l.log_date, l.log_usr_alias 
    					FROM log_hist as l ) AS lg 
    		 ON lg.log_usr_alias = u.usr_alias
    	WHERE u.usr_isValid = 1
    	ORDER BY log_date DESC

    Ojo a lo mejor me cole con la sintaxis porque yo no tengo tus tablas.... pero creo que se lee más fácil.

    Un saludo

    lunes, 5 de marzo de 2018 20:27
  • Hola,

      Puedes pasarnos una imagen del plan de ejecución para ver donde esta el mayor porcentaje de consumo en la consulta.


    Jose Miguel Salas C

    lunes, 5 de marzo de 2018 21:54