none
Consulta lenta (where id in(select id from ...)) RRS feed

  • Pregunta

  • Saludos,

    Tengo una consulta algo compleja, pero toda a la final consiste en:

    select * from tabla1 where id in(select id from tabla2 where a like '%x%')

    La consulta interna es mucho más compleja que la de muestra. Lo cierto es que se ejecuta veloz. No tarda ni 100 milisegundos. Pero la consulta total tarda minutos....

    Es extraño por que si extraigo el resultado de "select id from tabla2 where a like '%x%'" que por ejemplo de "20,14,18,21" y hago algo como

    select * from tabla1 where id in(20,14,18,21)  La consulta es veloz!

    No parece lógico que el motor de BD hace un proceso parecido al anterior? Es decir ejecuta la consulta interna y luego hace como si fuese un "where in(valores) "?

    Probé probando metiendo la consulta interna en una tabla temporal y luego haciendo un select * from tabla1 where id in (select id from #temptabla2)...

    Funciona... Rápido... Pero me parece matar un burro a pellizcos. Además no se cómo funcionará la tabla temporal con el tema de la concurrencia. Aunque por lo que se las tablas temporales funcionan con seguridad en el ámbito de un procedure.

    Alguna idea del por que esta consulta puede ser lenta? Qué puedo chequear en el execution plan? La consulta es mucho más compleja de lo que se ve.. En realidad intervienen como 6 tablas en la consulta interna, unions y demás, pero a la final el problema es el que coloco, pues se ejecuta rápido por si sóla...

    Gracias de antemano por cualquier aclaratoria y/o sugerencia,

     

     

     

     

     

     

    lunes, 13 de junio de 2011 22:50

Respuestas

  • Si es normal... El optimizador de consultas tiene que leerse toda la tabla para determinar los valores que tu extraes por que tu like es %xxx%,  ¿esa consulta sola ya tarda verdad?.  Crea un índice que incluya a tu campo "a" y a tu campo id, y la pruebas de nuevo.

    También puede ser uqe al ser tu consulta más compleja, el query optimizer acabe usando un plan sub-optimo.  Lo que puedes hacer es probar esto que te digo, y si no te funciona, postearnos la estrucuturra de las tablas, el número aproximado de registros en cada tabla y la query completa.. por si pudieramos darle una vuelta.


    Comparte lo que sepas, aprende lo que no sepas (FGG) http://www.portalsql.com</a
    • Propuesto como respuesta Normannp martes, 14 de junio de 2011 8:59
    • Marcado como respuesta Eder Costa jueves, 16 de junio de 2011 17:20
    martes, 14 de junio de 2011 7:36
    Moderador
  • Coincido con lo que te comenta Miguel Egea.

    Lo cierto es que estas haciendo una subconsulta dentro de una consulta, (yo siempre intento evitar esto, y apoyarme en distintas estructuras en la medida de lo pasible, como por ejem: join...) y encima esa subconsulta utiliza un like que suelen ser pesados y más aun si usas % delante y detrás de la cadena a buscar (piensa que en cada campo tiene que encontrar si existe una combinación =, el motor de base de datos busca su dato delante y detrás de cualquier cadena de cero o más caracteres, para lo que puede depender también la definición del campo…)


     Norman M. Pardell 

    ||Microsoft Certified IT Professional|| Database Administrator. Database Developer. SQL Server 2008


    • Marcado como respuesta Eder Costa jueves, 16 de junio de 2011 17:20
    martes, 14 de junio de 2011 8:59

Todas las respuestas

  •  

    Aquí encontré unas alternativas, pero nada...

     

    http://stackoverflow.com/questions/6135376/mysql-select-where-field-in-subquery-extremely-slow-why

     

    ¿Cómo se comportará el motor de base de datos aquí?

     

     

    martes, 14 de junio de 2011 0:44
  • Si tienes localizado el problema, aunque la consulta real sea más compleja puedes analizar el plan de ejecución de esa parte de la consulta y ponerlo aquí para que los demás podamos verlo también y dar nuestra opinión.

    El enlace que has pasado sirve de poco porque el motor del que hablan es MySQL, no SQL Server

    martes, 14 de junio de 2011 7:34
  • Si es normal... El optimizador de consultas tiene que leerse toda la tabla para determinar los valores que tu extraes por que tu like es %xxx%,  ¿esa consulta sola ya tarda verdad?.  Crea un índice que incluya a tu campo "a" y a tu campo id, y la pruebas de nuevo.

    También puede ser uqe al ser tu consulta más compleja, el query optimizer acabe usando un plan sub-optimo.  Lo que puedes hacer es probar esto que te digo, y si no te funciona, postearnos la estrucuturra de las tablas, el número aproximado de registros en cada tabla y la query completa.. por si pudieramos darle una vuelta.


    Comparte lo que sepas, aprende lo que no sepas (FGG) http://www.portalsql.com</a
    • Propuesto como respuesta Normannp martes, 14 de junio de 2011 8:59
    • Marcado como respuesta Eder Costa jueves, 16 de junio de 2011 17:20
    martes, 14 de junio de 2011 7:36
    Moderador
  • Releyendo el mensaje de Juliovbhlp me entran dudas. Por un lado dice que la consulta interna es veloz ("La consulta interna es mucho más compleja que la de muestra. Lo cierto es que se ejecuta veloz. No tarda ni 100 milisegundos.") pero luego comenta que las pruebas que hace es sustituyendo el '%x%' por valores concretos ("Es extraño por que si extraigo el resultado de "select id from tabla2 where a like '%x%'" que por ejemplo de "20,14,18,21" y hago algo como select * from tabla1 where id in(20,14,18,21)  La consulta es veloz!"), lo cual no es correcto porque no se está comparando lo mismo.

    Lo lógico es lo que dice Miguel, que una consulta del tipo '%x%' debería ser lenta porque impide a SQL Server usar de forma eficiente un índice sobre el campo que filtra (en caso de que exista), pero los comentarios anteriores no me lo dejan tan claro.

    martes, 14 de junio de 2011 8:10
  • Coincido con lo que te comenta Miguel Egea.

    Lo cierto es que estas haciendo una subconsulta dentro de una consulta, (yo siempre intento evitar esto, y apoyarme en distintas estructuras en la medida de lo pasible, como por ejem: join...) y encima esa subconsulta utiliza un like que suelen ser pesados y más aun si usas % delante y detrás de la cadena a buscar (piensa que en cada campo tiene que encontrar si existe una combinación =, el motor de base de datos busca su dato delante y detrás de cualquier cadena de cero o más caracteres, para lo que puede depender también la definición del campo…)


     Norman M. Pardell 

    ||Microsoft Certified IT Professional|| Database Administrator. Database Developer. SQL Server 2008


    • Marcado como respuesta Eder Costa jueves, 16 de junio de 2011 17:20
    martes, 14 de junio de 2011 8:59