none
Lentitud en ejecución de consultas RRS feed

  • Pregunta

  • Estimados amigos, me estoy volviendo loco con esto, os explico a ver si podéis orientar. He montado un SQL Server 2012 Express en un pc servidor de última generación con estas carácterísticas:

    Procesador Six Core AMD Opteron 2.20Ghz, 4Gb RAM y Windows Server 2008 Foundation.

    Al SQL server le he importado una base de datos que, actualmente trabaja front-end y back-end sobre access 2010. En SQL server he vuelto a rehacer todas las relaciones entre tablas y arreglado algúna que otra incongruencia que no me dejaba pasar el SQL Server. He de decir que la base de datos, tal y como la tenía, el fichero con los datos, back-end, de Access estaba alojado en una carpeta del mismo servidor y a ella se conectaban unos siete equipos desde la misma red sin problemas de rendimiento alguno. Ahora he conectado por ODBC el frot-end de Access al SQL Server y noto una considerabla perdida de velocidad en la ejecución del programa llegando el caso, el algunos formularios que utilizan orígenes de datos de cuatro o cinco tablas, de tardar mas de cinco minutos en abrirse. Todo esto en intranet y dentro de la misma oficina. Esos mismos formularios desde usando el back-end de Access corren que se las pelan. No entiendo a que es debido esa merma de velocidad tan considerable. Por poner un ejemplo concreto, el formulario que he abierto muestra 4500 registros en pantalla pero su peso en Mb es pequeño, de hecho el total de la base de datos, con mas de cien tablas, es de unos 30Mb, lo que no debería ser un problema para el SQL Server. ¿Creeis que él rendiemiento puede venir por las limitaciones de SQL Server o por el tipo de consultas que muevo? si fuera por el tipo de consultas, Microsoft Access de back-end, que utiliza un sistema mas primario de conexión a datos también me daría mas problemas y sin embargo va muy bien. ¿Quizás puede que me haya olvidado de configurarle algo al SQL Server?

    Como siempre, os agradezco de antemano cualquier ayuda que podaís aportarme.

    jueves, 16 de agosto de 2012 16:28

Respuestas

  • Hola.

    ¿Llevaste a cabo las recomendaciones que te sugerí en este otro hilo http://social.msdn.microsoft.com/Forums/es-ES/sqlserveres/thread/c406118f-5337-45d2-ac98-36e718f2e4d8/#c406118f-5337-45d2-ac98-36e718f2e4d8?

    No busques cuestiones de mala instalación o configuración de SQL Server, de hecho si vienes de Access lo lógico es notar una más que notable ganancia de rendimiento, dejando las opciones de configuración por defecto de la instalación, y aún siendo la edición Express. Lo que hay que estudiar son las sentencias que se ejecutan, la cantidad de registros que se mandan al cliente cada vez, cuestiones críticas como la concurrencia y el nivel de aislamiento.

    En esa línea, deberías desde ya evaluar las esperas y a localizar las sentencias que más recursos consumen en su ejecución, así como apoyarte en contadores de rendimiento para detectar cuellos de botella. Pero es que ni siquiera eso debería preocuparte aún, como te comenté, pon una traza de Profiler para poder saber qué es lo que sucede cuando se arranca la aplicación, cuánto tardan las consultas, cuántos registros se retornan al cliente, cuántas lecturas lógicas se realizan, etc. Y eso sin entrar a valorar el modelo de datos, lo normalizado que esté, los tipos de datos empleados, si cuentas con índices clustered pequeños y crecientes, si realizas las operaciones básicas de mantenimiento (reindexación, chequeos de integridad, copias de seguridad), etc. Es decir, todo un mundo, como tú mismo dices, pero que irás aprendiendo. 

    Otra guía básica de optimización, crear los índices que las propias estadísticas de uso te sugieren. Voy a ver si preparo un post en mi blog para contarlo y te dejo aquí el link, es algo trivial, el propio motor te sugiere qué índices vendrían bien a las sentencias que se están ejecutando. No es para seguir al pie de la letra, pero sí puede darte una idea de cómo empezar a manejarte.


    Alberto López Grande
    SQL Server MVP
    Visita mi blog en http://qwalgrande.com
    Sígueme en twitter en http://twitter.com/qwalgrande

    • Marcado como respuesta Conrrad69 viernes, 17 de agosto de 2012 12:26
    viernes, 17 de agosto de 2012 10:25
    Moderador
  • Hola,conrrad

    Creo que todos pasamos por eso, siempre al inicio es difícil, pero no te desesperes, siempre hay muchas personas que le ayudan a uno.

     

    • ahora que has identificado el query que está generando la lentitud, te aconsejo que análisis el plan de ejecución.
    • Primero ingresa al Sql Server Management Studio, conéctate al servido y la base de datos.
    • Selecciona new query.
    • Copia el query.
    • Antes de correrlo activa que se muestre el plan de ejecución.
    • Incluede Actual Execution Plan.
    • Ejecuta la consulta.
    • Al finalizar la consulta se te mostrara los resultados y el plan de ejecusion.
    • Lo importante es ver, que sección del query tiene el mayor costo.
    • Cuando identifique que sección tiene el mayor costo, verifica que tipo de operacion estas realizando.
    •       Operación de Join.
    •       Order By
    •        group by
    •       Agregaciones(sum, count, max)
    •       Etc
    • Dependiendo eso, debes crear un nuevo índice, realizar un include de columnas a un índice, crear estadísticas.

    Ejemplo demostrativo.

    select [dbo].[TblDemo01].[id],[dbo].[TblDemo01].[Campo3],count( [dbo].[tblDemo02].id)
    FROM [dbo].[TblDemo01] INNER JOIN
         [dbo].[tblDemo02] on
    	 [dbo].[TblDemo01].id=[dbo].[tblDemo02].id
    where [dbo].[TblDemo01].[Campo3] ='ahias portillo' AND
          [dbo].[tblDemo02].[valor] NOT LIKE '%2%'
    group by  [dbo].[TblDemo01].[id],[dbo].[TblDemo01].[Campo3]

    Ver plan de ejecusion

    Analicemos el plan de ejecución.

    1.  Puedes ver dos acciones que tiene el mayor costo en la ejecución de la consulta.

    1. Tienes un index scan de la tabla [dbo].[TblDemo01], esto es debido a que en la tabla solo se ha definido el índice por llave primaria, en la consulta se tiene un filtro por un campo que no es la llave y no es índice, debo decir que un Index Scan no es completamente malo, lo ideal es que tengas Index Seek, en este caso yo creare un índice por la columna  [dbo].[TblDemo01].[Campo3] Cuando creo ese índice logro el Index Seek, esto mejora el rendimiento si tenemos grandes cantidad de datos.
    2. Continuando con el análisis puedes ver que hay un Table Scan, eso es malo en consultas de grandes cantidades de datos, para eliminarlos debes crear índices por los campos de Join en este caso estamos haciendo un Join por el Campo ID, ejecutamos nuevamente la consulta y podrás ver un nuevo plan de ejecución.

    Analicemos nuevamente el plan de ejecución.

    o     

    Mucha suerte Amigo.


    ahias

    • Marcado como respuesta Conrrad69 lunes, 20 de agosto de 2012 8:40
    lunes, 20 de agosto de 2012 1:05

Todas las respuestas

  • Hola Conrrad,

    Hay varias posibilidades. Una podria ser que necesitas optimizar la consulta en el nuevo servidor. Otra podria ser tu red. Otra podria ser que Access esta teniendo algun problema para conectarse y ejecutar la consulta.

    Puedes ejecutar la misma consulta que haces para el formulario que demora directamente a SQL Server usando SSMS para ver que clase de rendimiento encuentras?

    Haz esto de forma local y luego de forma remota. Esto ultimo para ver como se comporta tu red cuando mueves esos mismos datos.

    Si la consulta ejecutada localmente desde SSMS demora, es posible que necesites algunos indices en tu nueva base de datos. Pero no nos adelantemos. Haz las pruebas y luegos nos cuentas.

    Saludos,

    Monica


    This posting is provided "AS IS" with no warranties, and confers no rights. Please remember to click "Mark as Answer" and "Vote as Helpful" on posts that help you. This can be beneficial to other community members reading the thread.

    jueves, 16 de agosto de 2012 19:43
  • Gracias Mónica por responder, mañana haré esa prueba a ver el rendimiento y te cuento. 

    Ahora bien, antes de hacerlas mañana, ya que ahora no tengo el servidor a mano, voy a matizar un par de pruebas que estoy haciendo en otro equipo y mis impresiones.

    En otro equipo que no está conectado a la red y con unas prestaciones algo menores que el servidor, he instalado el SQL Server Express X86, matizo la versión porque en el servidor instalé la versión de 64 bits y me aparece todo en Inglés, mmmm...., y en este equipo la versión X86 en español, que igual con las mil pruebas que he hecho me bajé la versión de 64 bits en inglés. Bueno, sigo con el tema, en este equipo de prueba he restaurado una copia de la base de datos que estoy usando en el servidor y en este mismo equipo, he ejecutado el front-end de Access y curiosamente, aquí ¡¡¡¡ VA BIEN !!!!!, no hay el retardo que existe en el servidor. He realizado una consulta compleja desde el SSMS y también va bien.

    Si me permites voy a pensar en voz alta: 

    1 - ¿Es posible que la versión del SQL Server del servidor esté mal, dañada, estropeada, etc...?, como ultimo recurso desinstalaré la versión de 64Bit en Inglés e instalaré la x86 en Español, por si un caso.

    2 - Si en local, mismo equipo para el server SQL y el Access, va bien, podría pensar que fuera la red la que está fallando, pero lo descarto desde este mismo momento pues funcionando solo con los dos ficheros de Access en esa red todo funciona bien, además hay otras aplicaciones usando la red y todo es correcto, no se cuelga ni hay latencias preocupantes ni nada parecido.

    3 - Me indicas el tema de los índices, yo en Access los tengo creados, a parte de los campos clave que ya lo llevan, algún que otro campo puntual le he creado los indices y bien es cierto que cuando importé las tablas al SQL Server muchas de las cosas que deberían de haberse importado me ha tocado modificarlas a mano como las claves principales que he tenido que aplicarlas a todas las tablas de nuevo, las relaciones que no se importan, un fastidio, los campos Si/No que en SQL me los transforma a Bin, y es posible que me deje algo en el tintero así que lo mas probable es que los índices que tenía por ahí sueltos tampoco los haya importado, aún así, y si ese fuera el motivo de la latencia creo que tampoco funcionaría en el segundo equipo de pruebas. Bueno y doy por hecho de que los campos que vuelto a marcar como clave me los ha indizado el SQL Server.

    Seguiré consultando con la almohada esta noche a ver que tal se me da y mañana, con las pruebas pertinentes, las vuelvo a comentar.

    Insisto, muchas gracias por la ayuda que me estáis prestando, pues sin ella estoy muy perdido.

    jueves, 16 de agosto de 2012 20:26
  • El SQL Server Express Edition es totalmente limitada en cuanto a performance (solo reconoce 1 GB de ram, por ejemplo).

    Se usa para practicar, pero en ningún momento se usa para producción en un ambiente donde el rendimiento sea importante.

    Acá tengo el link de las características de las diferentes ediciones:

    http://msdn.microsoft.com/es-es/library/cc645993(v=sql.110).aspx


    MVP MCT MCTS Daniel Calbimonte

    http://elpaladintecnologico.blogspot.com

    jueves, 16 de agosto de 2012 20:44
  • Hola,

    Como menciona nuestro colega los problemas pueden ser muchos.

    Te recomiendo hacer un monitoreo general  sobre tu servidor, en este caso programa unos contadores de rendimiento, esto con el objetivo de poder identificar patrones anormales.

    Contadores recomendados:

     

    Contadores de Servidor

    % Processor Time

    % detiempoen queel procesadorparaocupado

    Entre másbajomejor

    %Privileged Time

    Representael tiempoinvertidoen el kernel haciendoI/O porejemplo

    Si superael 80%-90% pormásde 15 minsy el contador“Disk Activity” estáaltoentoncesel problemaesde disco

    % User Time

    Tiempodedicadoa los programascomoSQL o Antivirus

    %User Time + % Privilege Time = % Processor Time, entre másbajomejor

    Interrupts/Sec

    Cantidadde interrupcionesdel hardware

    Porencimade 1000 indicaproblemascon el hardware o drivers

    % Total Processor Time

    Promediode usode todoslos procesadores

    > 90% pormásde 20 minsindicaproblemasde procesador

    Processor Queue Length

    Indicacuántosprocesoshay en esperade ser atendidosporel procesador

    > 2 porprocesadordurante20 minutosindicaqueelcuellode botellaesel procesador

    % Processor Time

    El tiempoinvertidoen el procesoseleccionado

    Entre máscercanoa cero mejor

    % UserTime

    El tiempoutilizadoporusuario, ej. Cuántoconsume el antivirus

    Entre máscercanoa cero mejor

    Working Set

    Reportala cantidadde memoriautilizadaporun proceso

    SirveparamedircuántamemoriautilizaSQL Server. Deberíaser menoral 90% de todala RAM

    Private Bytes

    Cuántosbytes tieneun procesoqueno puedeser compartidacon otros

    PuededecircuántamemoriausaSqlservr.exe

    Virtual Bytes

    Total de la memoriavirtual utilizadaporSQL Server

    Para saber cuándousaSQL

    % Avg. Disk Sec/Transfer

    Quétan rápidose muevenlos datosen cadatransferencia, en segundos. Tiempode respuestadel disco

    > 0.3 segsindicaun disco lento o con fallos

    Avg. Disk Sec/Read

    Tiempode respuestaen laslecturas

    Entre másbajomejor

    Avg.Disk Sec/Write

    Tiempode respuestaen lasescrituras

    Entre másbajomejor

    % Disk Time

    Tiempoquepasaocupadoel disco en I/O

    > 90% indicacuellode botella

    Avg. Disk Queue Length

    Cantidadde solicitudes esperandoser atendidasporel disco

    > 2 indicacuellode botella

    Current Disk Queue Length

    Muestrael largode la cola real, no solo el promedio

    Cercanoa cero

    % Disk Read Time

    % Tiempoquese gastaen lecturas

    Entre másbajomejor

    % Disk Write Time

    % Tiempoquese gastaen lecturas

    Entre másbajomejor

    % Idle Time

    % Tiempoquepasael disco desocupado

    Entre másalto mejor

    Avg. Disk Bytes/Transfer

    El tamañode lasoperacionesde I/O. Es decircuántositems procesaporoperación.

    Entre másalto mejor

    Disk Bytes/sec

    Tasade transferenciade bytes

    Entre másalto mejor

    Available Mbytes

    Cuántamemoriaquedadisponible

    Entre másalto mejor

    Pages/Sec

    Númerode páginasde memoriasolicitadasy no disponibles, porlo quese leendeldisco (paginación)

    Entre másbajomejor

    CommittedBytes

    La memoriafísicaqueha sidoreservadaen el discoparapaginación

    Crecede acuerdoa la memoriaRAM disponible. La altapaginaciónno esbuena

    CommitedLimit

    Cantidadde memoriavirtual (en disco) quesepuedeutilizarsin extender el archivode paginación

    Crecede acuerdoa la memoriaRAM disponible.

     

     

    Contadores de Sql Server

    Buffer Manager: BufferCache Hit Ratio

    % de páginasencontradasen el buffer cache win tenerqueleer de disco

    >90

    :Buffer Manager: Total Pages

    La cantidadtotal de páginasen el buffer pool

    Cuántomideel buffer de SQL

    :Memory Manager: Total Server Memory (KB)

    CuántamemoriautilizaSQL Server

    Si esmenorqueTarget Server Memory (KB) entoncesSQL tienesuficientememoria

    :Memory Manager: Target Server Memory (KB)

    IndicacuántamemoriadesearíatenerSQLServer paraser máseficiente

     

     

    Si observas algún patrón anormal en algunos de estos contadores, te recomiendo analizar los querys de tu base de datos, por medio de un profile y tunning, si no posees esas herramientas, me puede consultar para darte un poco de ayuda.


    ahias

    jueves, 16 de agosto de 2012 20:47
  • El SQL Server Express Edition es totalmente limitada en cuanto a performance (solo reconoce 1 GB de ram, por ejemplo).

    Se usa para practicar, pero en ningún momento se usa para producción en un ambiente donde el rendimiento sea importante.

    Acá tengo el link de las características de las diferentes ediciones:

    http://msdn.microsoft.com/es-es/library/cc645993(v=sql.110).aspx


    MVP MCT MCTS Daniel Calbimonte

    http://elpaladintecnologico.blogspot.com

    Hola Dani, estoy de acuerdo contigo que la versión no debe ser muy potente pero tampoco la base de datos lo es, creo. A pesar de tener muchas tablas, un total de 30Mb creo que era poco y suficiente para moverlo la versión express. Es mas, haciendo las pruebas como comenté en el post anterior, ejecutando Server y front-end en otro equipo de peores características que el Servidor donde irá definitivamente montado todo el sistema, la velocidad de ejecución del programa es bastante aceptable por lo que intuyo que, a pesar de las limitaciones de la versión Express, debería de mover esta base de datos sin problemas.

    Además la idea era precisamente empezar con la Express y con el tiempo, si la base lo demanda, adquirir la licencia pertinente que permita crecer la empresa.

    Bueno, gracias por responder, le hecho un vistazo al enlace.

    viernes, 17 de agosto de 2012 5:10
  • Hola ahias, al mundo SQL Server acabo de llegar con una mano alante y otra detrás, como se suele decir por mi tierra, y aún ando peleándome y descubriendo y tropezándome y descubriendo y volviendo a tropezar... etc. "Autodidacta  hasta la muerte".

    Bueno aunque entiendo perfectamente la función de los contadores de rendimiento, para mi, son otro descubrimiento que ni sabía que existían. ¿Necesito alguna herramienta opcional que no tenga instalada en la versión Express? ¿Mas o menos como los configuro y los pruebo?

    Gracias por la ayuda.

    viernes, 17 de agosto de 2012 5:17
  • Hola.

    ¿Llevaste a cabo las recomendaciones que te sugerí en este otro hilo http://social.msdn.microsoft.com/Forums/es-ES/sqlserveres/thread/c406118f-5337-45d2-ac98-36e718f2e4d8/#c406118f-5337-45d2-ac98-36e718f2e4d8?

    No busques cuestiones de mala instalación o configuración de SQL Server, de hecho si vienes de Access lo lógico es notar una más que notable ganancia de rendimiento, dejando las opciones de configuración por defecto de la instalación, y aún siendo la edición Express. Lo que hay que estudiar son las sentencias que se ejecutan, la cantidad de registros que se mandan al cliente cada vez, cuestiones críticas como la concurrencia y el nivel de aislamiento.

    En esa línea, deberías desde ya evaluar las esperas y a localizar las sentencias que más recursos consumen en su ejecución, así como apoyarte en contadores de rendimiento para detectar cuellos de botella. Pero es que ni siquiera eso debería preocuparte aún, como te comenté, pon una traza de Profiler para poder saber qué es lo que sucede cuando se arranca la aplicación, cuánto tardan las consultas, cuántos registros se retornan al cliente, cuántas lecturas lógicas se realizan, etc. Y eso sin entrar a valorar el modelo de datos, lo normalizado que esté, los tipos de datos empleados, si cuentas con índices clustered pequeños y crecientes, si realizas las operaciones básicas de mantenimiento (reindexación, chequeos de integridad, copias de seguridad), etc. Es decir, todo un mundo, como tú mismo dices, pero que irás aprendiendo. 

    Otra guía básica de optimización, crear los índices que las propias estadísticas de uso te sugieren. Voy a ver si preparo un post en mi blog para contarlo y te dejo aquí el link, es algo trivial, el propio motor te sugiere qué índices vendrían bien a las sentencias que se están ejecutando. No es para seguir al pie de la letra, pero sí puede darte una idea de cómo empezar a manejarte.


    Alberto López Grande
    SQL Server MVP
    Visita mi blog en http://qwalgrande.com
    Sígueme en twitter en http://twitter.com/qwalgrande

    • Marcado como respuesta Conrrad69 viernes, 17 de agosto de 2012 12:26
    viernes, 17 de agosto de 2012 10:25
    Moderador
  • Hola.

    Lo dicho, recién salido del horno:

    http://qwalgrande.com/2012/08/17/que-indices-cree-tu-servidor-que-deberian-crearse/


    Alberto López Grande
    SQL Server MVP
    Visita mi blog en http://qwalgrande.com
    Sígueme en twitter en http://twitter.com/qwalgrande

    viernes, 17 de agosto de 2012 11:00
    Moderador
  • Hola Alberto, bueno como a todos agradezco enormemente la ayuda. Las recomendaciones que me sugeriste el otro día tenía que ponerlas en práctica hoy pero por cuestiones técnicas ya no me ha dado tiempo de realizarlas. He realizado las pruebas esta mañana en el mismo servidor, in situ, y he determinado que mi problema de rendimiento se debe en parte a que ciertos formularios utilizan como origen de datos consultas bastante complejas donde intervienen varias tablas y, en algunos casos, campos calculados. Y para el que le pueda servir de algo os expongo los pasos que he estado probando:

    1 - Visto el origen de datos (Una consulta) de uno de los formularios que mas problemas he tenido de rendimiento he ido al PC Servidor y desde el Management Studio he creado una vista con las mismas características que el origen de datos de mi formulario y acto seguido la he ejecutado obteniendo la carga de unos 5000 registros aproximadamente en un tiempo que yo considero aceptable, apenas tres segundos.

    2 - Descartando que el problema pueda ser del servidor he ido a la máquina cliente, donde también tengo instalado el Management Studio, he conectado este al servidor y a la base de datos origen de mis desvelos. Como ya tenía la vista creada la he ejecutado desde el cliente, obteniendo la misma velocidad al cargar los registros que ejecutándola directamente en el PC Servidor.

    3 - Descartando que el problema fuera de la red, he vinculado dicha Vista con mi programa de Microsoft Access, que me la vincula como si de una tabla de Access se tratase, la he abierto y, voilá, los datos los carga volados. A continuación he ejecutado la consulta de Access, que es igual que la vista creada SQL Server, y de la que se nutre el formulario, obteniendo unos tiempos de carga patéticos.

    4 - Conclusión: Las consultas mas complejas deben de estar creadas en el servidor SQL Server (Vistas) y tenerlas vinculadas con Access para que sea el servidor quien la procese y devuelva a Access los registros y los campos necesarios. Es la única forma de que Access se maneje bien. No obstante me he llevado una desilusión enorme puesto que daba por echo de que si Microsoft Access, con dos ficheros, front-end vinculado al otro fichero Back-end situado en una carpeta del PC servidor, va estupendamente, entiendo que al pasar los datos a SQL Server, a pesar de que las consultas sigan estando en Access, debería de ir muuuuuucho mejor y no ha sido así.

    Solución propuesta: Dado que la base de dato al uso controla el 80% de la gestión de la empresa y por ende no podemos dejarla inactiva mientras corregimos los problemas, hablamos que tenemos mas de 300 consultas y la mitad de ellas muy complejas, y que tampoco podemos dejarla operativa con la lentitud que abre algunos formularios, hemos decidido dejarla como estaba, trabajando Back-end y front-end en MS Access, y con el tiempo, a lo largo del año que viene ir copiando esas consultas al servidor, optimizándolas y cuando tengamos claro que hemos corregido los rendimientos, volver a probar.

    No obstante, agradezco todos vuestros consejos, no solo estos, si no lo de otros post y durante estos meses procuraré ponerme las pilas, seguir dando el tostón por aquí e ir aprendiendo mas sobre SQL Server y que no os quepa duda que probaré los contadores y los rendimientos de las tablas.

    Gracias.

    viernes, 17 de agosto de 2012 12:25
  • Hola,conrrad

    Creo que todos pasamos por eso, siempre al inicio es difícil, pero no te desesperes, siempre hay muchas personas que le ayudan a uno.

     

    • ahora que has identificado el query que está generando la lentitud, te aconsejo que análisis el plan de ejecución.
    • Primero ingresa al Sql Server Management Studio, conéctate al servido y la base de datos.
    • Selecciona new query.
    • Copia el query.
    • Antes de correrlo activa que se muestre el plan de ejecución.
    • Incluede Actual Execution Plan.
    • Ejecuta la consulta.
    • Al finalizar la consulta se te mostrara los resultados y el plan de ejecusion.
    • Lo importante es ver, que sección del query tiene el mayor costo.
    • Cuando identifique que sección tiene el mayor costo, verifica que tipo de operacion estas realizando.
    •       Operación de Join.
    •       Order By
    •        group by
    •       Agregaciones(sum, count, max)
    •       Etc
    • Dependiendo eso, debes crear un nuevo índice, realizar un include de columnas a un índice, crear estadísticas.

    Ejemplo demostrativo.

    select [dbo].[TblDemo01].[id],[dbo].[TblDemo01].[Campo3],count( [dbo].[tblDemo02].id)
    FROM [dbo].[TblDemo01] INNER JOIN
         [dbo].[tblDemo02] on
    	 [dbo].[TblDemo01].id=[dbo].[tblDemo02].id
    where [dbo].[TblDemo01].[Campo3] ='ahias portillo' AND
          [dbo].[tblDemo02].[valor] NOT LIKE '%2%'
    group by  [dbo].[TblDemo01].[id],[dbo].[TblDemo01].[Campo3]

    Ver plan de ejecusion

    Analicemos el plan de ejecución.

    1.  Puedes ver dos acciones que tiene el mayor costo en la ejecución de la consulta.

    1. Tienes un index scan de la tabla [dbo].[TblDemo01], esto es debido a que en la tabla solo se ha definido el índice por llave primaria, en la consulta se tiene un filtro por un campo que no es la llave y no es índice, debo decir que un Index Scan no es completamente malo, lo ideal es que tengas Index Seek, en este caso yo creare un índice por la columna  [dbo].[TblDemo01].[Campo3] Cuando creo ese índice logro el Index Seek, esto mejora el rendimiento si tenemos grandes cantidad de datos.
    2. Continuando con el análisis puedes ver que hay un Table Scan, eso es malo en consultas de grandes cantidades de datos, para eliminarlos debes crear índices por los campos de Join en este caso estamos haciendo un Join por el Campo ID, ejecutamos nuevamente la consulta y podrás ver un nuevo plan de ejecución.

    Analicemos nuevamente el plan de ejecución.

    o     

    Mucha suerte Amigo.


    ahias

    • Marcado como respuesta Conrrad69 lunes, 20 de agosto de 2012 8:40
    lunes, 20 de agosto de 2012 1:05
  • Hola

    Muchos colegas han hablado de las DMV, te recomendares las consultas que mas utilizado en una optimizacion de base de datos.


    • Indices que no existe y que son costos para la base de datos: Esta consulta te provee un impacto si creas el indice, te recomienda que columnas debe llevar el indices y que include debes utilizar.
    SELECT  
            [Total Cost]  = ROUND(avg_total_user_cost * avg_user_impact * (user_seeks + user_scans),0) 
            , avg_user_impact
            , TableName = statement
            , [EqualityUsage] = equality_columns 
            , [InequalityUsage] = inequality_columns
            , [Include Cloumns] = included_columns
    FROM        sys.dm_db_missing_index_groups g 
    INNER JOIN    sys.dm_db_missing_index_group_stats s 
           ON s.group_handle = g.index_group_handle 
    INNER JOIN    sys.dm_db_missing_index_details d 
           ON d.index_handle = g.index_handle
    ORDER BY [Total Cost] DESC;
    


    • Indices que existen pero que no se usan, y generan impactos en la base de datos.
    -- Create required table structure only.
    -- Note: this SQL must be the same as in the Database loop given in the following step.
    SELECT TOP 1
            DatabaseName = DB_NAME()
            ,TableName = OBJECT_NAME(s.[object_id])
            ,IndexName = i.name
            ,user_updates    
            ,system_updates    
            -- Useful fields below:
            --, *
    INTO #TempUnusedIndexes
    FROM   sys.dm_db_index_usage_stats s 
    INNER JOIN sys.indexes i ON  s.[object_id] = i.[object_id] 
        AND s.index_id = i.index_id 
    WHERE  s.database_id = DB_ID()
        AND OBJECTPROPERTY(s.[object_id], 'IsMsShipped') = 0
        AND    user_seeks = 0
        AND user_scans = 0 
        AND user_lookups = 0
        AND s.[object_id] = -999  -- Dummy value to get table structure.
    ;
    
    -- Loop around all the databases on the server.
    EXEC sp_MSForEachDB    'USE [?]; 
    -- Table already exists.
    INSERT INTO #TempUnusedIndexes 
    SELECT TOP 10    
            DatabaseName = DB_NAME()
            ,TableName = OBJECT_NAME(s.[object_id])
            ,IndexName = i.name
            ,user_updates    
            ,system_updates    
    FROM   sys.dm_db_index_usage_stats s 
    INNER JOIN sys.indexes i ON  s.[object_id] = i.[object_id] 
        AND s.index_id = i.index_id 
    WHERE  s.database_id = DB_ID()
        AND OBJECTPROPERTY(s.[object_id], ''IsMsShipped'') = 0
        AND    user_seeks = 0
        AND user_scans = 0 
        AND user_lookups = 0
        AND i.name IS NOT NULL    -- Ignore HEAP indexes.
    ORDER BY user_updates DESC
    ;
    '
    
    -- Select records.
    SELECT TOP 10 * FROM #TempUnusedIndexes ORDER BY [user_updates] DESC
    -- Tidy up.
    DROP TABLE #TempUnusedIndexes
    

    • Indica la fragmentacion de los indices, recuerda que puede existir el indice pero si este tiene una gran fragmentacion no es efectivo en la consulta.
    -- Create required table structure only.
    -- Note: this SQL must be the same as in the Database loop given in the -- following step.
    SELECT TOP 1 
            DatbaseName = DB_NAME()
            ,TableName = OBJECT_NAME(s.[object_id])
            ,IndexName = i.name
            ,[Fragmentation %] = ROUND(avg_fragmentation_in_percent,2)
    INTO #TempFragmentation
    FROM sys.dm_db_index_physical_stats(db_id(),null, null, null, null) s
    INNER JOIN sys.indexes i ON s.[object_id] = i.[object_id] 
        AND s.index_id = i.index_id 
    WHERE s.[object_id] = -999  -- Dummy value just to get table structure.
    ;
    
    -- Loop around all the databases on the server.
    EXEC sp_MSForEachDB    'USE [?]; 
    -- Table already exists.
    INSERT INTO #TempFragmentation 
    SELECT TOP 10
            DatbaseName = DB_NAME()
            ,TableName = OBJECT_NAME(s.[object_id])
            ,IndexName = i.name
            ,[Fragmentation %] = ROUND(avg_fragmentation_in_percent,2)
    FROM sys.dm_db_index_physical_stats(db_id(),null, null, null, null) s
    INNER JOIN sys.indexes i ON s.[object_id] = i.[object_id] 
        AND s.index_id = i.index_id 
    WHERE s.database_id = DB_ID() 
          AND i.name IS NOT NULL    -- Ignore HEAP indexes.
        AND OBJECTPROPERTY(s.[object_id], ''IsMsShipped'') = 0
    ORDER BY [Fragmentation %] DESC
    ;
    '
    
    -- Select records.
    SELECT TOP 10 * FROM #TempFragmentation ORDER BY [Fragmentation %] DESC
    -- Tidy up.
    DROP TABLE #TempFragmentation
    

    • Consultas que sufren bloqueos, esto es importante.
    SELECT TOP 10 
     [Average Time Blocked] = (total_elapsed_time - total_worker_time) / qs.execution_count
    ,[Total Time Blocked] = total_elapsed_time - total_worker_time 
    ,[Execution count] = qs.execution_count
    ,[Individual Query] = SUBSTRING (qt.text,qs.statement_start_offset/2, 
             (CASE WHEN qs.statement_end_offset = -1 
                THEN LEN(CONVERT(NVARCHAR(MAX), qt.text)) * 2 
              ELSE qs.statement_end_offset END - qs.statement_start_offset)/2) 
    ,[Parent Query] = qt.text
    ,DatabaseName = DB_NAME(qt.dbid)
    FROM sys.dm_exec_query_stats qs
    CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) as qt
    ORDER BY [Average Time Blocked] DESC;
    

    Esta informacion fue tomada del siguiente articulo:http://msdn.microsoft.com/es-es/magazine/cc135978.aspx#S1

    Muchas suerte.



    ahias

    lunes, 20 de agosto de 2012 1:57
  • Ahias, muchas gracias por la información, no me cabe la menor duda de que me queda mucho por aprender de este mundo pero con la calidad humana de estos foros lo tendré mas fácil.

    Sorprendido me he quedado con la herramienta que me has expuesto. Que no te quepa la menor duda de que me pondré con ella a ver las conclusiones que le saco a esas consultas "Puñeteras".

    Muchísimas Gracias.

    lunes, 20 de agosto de 2012 8:44