Rendimiento

Configurando SQL Server para SharePoint

Configurando SQL Server para SharePoint

En el post de hoy vamos a continuar configurando nuestro SQL Server para alojar bases de datos de SharePoint. Si ayer vimos lo necesario para diseñar correctamente la infraestructura y las peculiaridades de una instalación con este fin hoy vamos a continuar con las configuraciones específicas que tendremos que implementar para lograr el mejor rendimiento posible.

En el menú del día tenemos de plato principal las buenas prácticas de configuración y terminaremos con las particularidades del mantenimiento de este tipo de bases de datos. 

Configuraciones específicas de SQL Server para SharePoint

Como hemos dicho, SharePoint necesita de una serie de configuraciones particulares en nuestros servidores de SQL Server. Si bien no estamos hablando de funcionalidades que existen en exclusiva para esta herramienta, la combinación de estas configuraciones nos permitirá sacar todo el partido posible de nuestras bases de datos.

Configuraciones de disco duro

Dedicamos gran parte del pasado post a este apartado, no es para menos, como os dije SharePoint es una herramienta que hace un uso intensivo de este recurso. Sobre todo lo que ya hablamos quiero añadir que una vez instalado SQL Server, y si tenemos varios tipos distintos de discos para almacenar nuestras bases de datos, usaremos nuestros discos más rápidos para la TempDB y los registros de transacciones de las bases de datos. Seguido por los archivos de las bases de datos de búsqueda.
Para terminar almacenaremos los archivos de datos de las bases de datos de contenido y por último las bases de datos de configuración. A poder ser usaremos discos optimizados para escrituras en la base de datos TempDB y en los logs de transacciones y optimizados para lectura en las bases de datos de búsqueda y contenido. Si nuestro SharePoint está más enfocado a la lectura que a las escrituras priorizaremos los archivos de datos sobre los logs de transacciones.
Recuerda también configurar el tamaño de bytes per cluster a 64kb tal como vimos en las buenas prácticas generales para SQL Server.

Configuración de memoria RAM

A nivel sistema operativo, configuraremos la paginación manualmente con un tamaño fijo de 1,5 veces el tamaño de la memoria RAM que tenga nuestro servidor. Este archivo de paginación estará en un disco dedicado lo más rápido posible.  En SQL Server configuraremos la memoria mínima y la máxima de SQL Server siempre dejando un mínimo de 3 o 4 Gb libres para que el sistema operativo pueda funcionar. Para estos servidores, siempre que tengamos un servidor SQL dedicado configuraremos el mismo valor de memoria mínimo y máximo. 

Para entender esto es necesario saber cómo funciona la asignación de memoria en SQL Server, veámoslo rápidamente. SQL Server gestiona los recursos de nuestra máquina a través de su propio subsistema operativo dedicado. Este SQL SO, además de gestionar las colas de CPU gestiona la memoria RAM. Cuando arrancamos SQL Server irá “cogiendo” memoria a medida que la necesite (hasta el valor máximo que hayamos asignado) y cuando deje de necesitarla se la quedará reservada. Si el sistema operativo tiene falta de memoria SQL “devolverá” la que no esté usando (hasta quedarse en el valor mínimo que hayamos definido). Esto quiere decir que nuestro SQL puede consumir menos RAM del mínimo que le hayamos asignado si hasta ese momento no ha necesitado de esa memoria.

Una vez que ya tenemos claro cómo funciona la gestión de memoria de SQL Server podemos entender lo que necesitamos para nuestro SQL Server para SharePoint. Asignaremos un valor mínimo igual más máximo y será el total de la RAM disponible menos los 3 o 4 Gb que necesita el sistema operativo y lo que estimemos que necesitan otras aplicaciones imprescindibles como las de copia de seguridad.

Otras configuraciones de SQL Server

Para continuar con las configuraciones de nuestra instancia de SQL Server las buenas prácticas hablan de activar la opción de comprimir backups. Como en este blog nos gusta profundizar en los temas vamos a entrar en detalle en este punto. Comprimir backup tiene un mayor consumo de recursos y un peor rendimiento a la hora de hacer y restaurar las copias de seguridad. Hablamos obviamente de recursos de CPU y RAM. El problema viene con el resto de recursos, disco y red. Como hablamos de bases de datos pesadas, el extra de coste en CPU y RAM se ve compensado por la reducción de disco y de red por lo que en este caso es una buena práctica recomendada.

Otra de las recomendaciones que nos da Microsoft para los servidores SQL Server para Sharepoint es configurar el Fill Factor al 80%. No vamos a entrar en detalle sobre esto ya que ya hemos hablado de ello en otro post.

Cerramos el apartado sobre las configuraciones hablando de la configuración de CPU, en este caso estableceremos el nivel de paralelismo a 1. El nivel de paralelismo indica cuántos núcleos de CPU usarán nuestras consultas, un valor elevado es ideal para servidores con pocas consultas pero pesadas mientras que en servidores con multitud de consultas un valor bajo nos ayudará a tener más consultas ejecutándose simultáneamente. Dado el alto volumen de transacciones simultáneas que va a generar SharePoint en nuestro SQL Server un valor distinto de 1 perjudicará enormemente el rendimiento. 

Configuraciones de bases de datos para SharePoint

Para nuestras bases de datos debemos asegurarnos de que no esté habilitada la opción AutoShink y que no haya ningún trabajo programado que reduzca los ficheros de bases de datos. Aunque esta es una recomendación para la mayoría de bases de datos, en el caso de SharePoint se suele decir que los shrink quedan reservados a ocasiones especiales cuando se haya borrado más del 50% de los datos por parte de un administrador del sitio y tengamos claro que ese espacio no se va a volver a necesitar.

De la misma manera deshabilitaremos la creación y la actualización automática de estadísticas ya que SharePoint se encargará automáticamente de su creación. El tema de las actualizaciones lo vamos a ver luego, cuando hablemos del mantenimiento.

Configuraciones de los ficheros de base de datos de SharePoint

Continuamos con los ficheros de base de datos y como no podía ser de otra manera también tienen configuraciones específicas. En este caso relativas a la distribución y crecimiento.  En una situación ideal, los administradores de SharePoint serán capaces de proporcionarnos el crecimiento esperado de las bases de datos en un año, en estos casos dimensionamos los ficheros en ese tamaño estimado más un 20% de margen. Sin embargo, la realidad es distinta, normalmente no sabremos la tasa de crecimiento anual. En estos casos dimensionamos nuestros ficheros al máximo (o cerca del máximo) del tamaño que hayamos estimado que vayan a crecer  en total(recuerda que en el anterior post explicamos la fórmula para calcular el crecimiento de las bases de datos).
Por lo general, Microsoft no recomienda bases de datos de más de 200Gb para SharePoint, en caso de necesitar más espacio deberá estar dividido en colecciones en distintas bases de datos. SharePoint tiene su propia herramienta para poder mover colecciones entre bases de datos. Tener los ficheros dimensionados a su máximo tamaño nos ahorrará el tiempo que dedica el motor de base de datos a ampliar el tamaño de estos cuando no tiene sitio para alojar información nueva y optimiza las escrituras en SharePoint. 

Crecimiento de los ficheros de base de datos de SharePoint

Sin embargo, aunque tengamos los ficheros dimensionados es importante configurarlos con crecimiento automático para que, en caso de ser necesario, puedan crecer. Configuraremos un crecimiento automático elevado, para evitar que cada transacción nueva tenga que dedicar tiempo a esta tarea. No tengáis miedo a los crecimientos en bloques de varios Gb, recordad que nuestros SharePoint van a almacenar documentos de varios cientos de Mb en ocasiones. Estableceremos crecimientos de 512 Mb para las bases de datos pequeñas y de 5 Gb para las bases de datos de más de 50 Gb. Usar porcentajes de crecimiento no es una práctica recomendada.

Por último, para los logs de transacciones, configuraremos un tamaño de un 25% o 30% del tamaño total de los ficheros de datos.

Distribución de los ficheros de base de datos de SharePoint

Configuraremos nuestras bases de datos de contenido con varios ficheros, a poder ser en varios discos (y varios LUNs) para ganar rendimiento de E/S. En estos casos usaremos la misma regla que usamos normalmente para la TempDB, crearemos un fichero por cada núcleo de nuestro procesador con un máximo de 8 ficheros. Es importante que todos los ficheros tengan el mismo tamaño inicial, pues crecerán a la vez y esto mejora el rendimiento. Si nuestro SQL Server es anterior a 2016 no hará crecer los ficheros a la vez por defecto y deberemos indicarlo con la traza -T1117 en el arranque.

Base de datos TempDB

Hablando de la TempDB, aprovisionaremos un tamaño inicial igual al 25% o 30% del total del tamaño de datos que hayamos estimado que vamos a tener. Repartiremos ese tamaño total entre tantos ficheros como CPUs tengamos con un máximo de 8. Todos los ficheros tendrán el mismo tamaño inicial.

Base de datos Model

SharePoint creará las bases de datos que necesite, por lo que es importante trasladar todas las anteriores consideraciones a nuestra base de datos model a fin de que se puedan aplicar automáticamente en todas las nuevas bases de datos.

Mantenimiento de bases de datos de SharePoint

Como en cualquier otro servidor SQL Server se hace imprescindible configurar un plan de copias de seguridad y un chequeo de integridad de las bases de datos periódicamente. 

En cuanto al mantenimiento de índices y estadísticas tenemos que conocer la versión de SharePoint que se está ejecutando. En SharePoint 2012 o inferior este gestionará el plan de mantenimiento de índices y estadísticas por lo que no deberemos nosotros duplicar ese trabajo. Para SharePoint 2013 o superior si que debemos configurar nuestros planes de mantenimiento con normalidad. Como ya sabéis, en estos casos yo os recomiendo las herramientas de Ola Hallengren.

Conclusión

Hoy hemos aprendido a configurar nuestros servidores SQL Server para alojar las bases de datos de SharePoint. Es importante repetir estos pasos en todos los servidores de la granja de SharePoint para sacar todo el partido de esta aplicación. Tanto si vais a desplegar un nuevo servidor SharePoint como si ya lo tenéis, aplicad estos consejos y los del post de instalación y veréis como mejora el rendimiento. Yo lo hice en un cliente y os aseguro que el volumen de incidencias por lentitud se redujo drásticamente. 

Y ya no me enrollo más, recuerda que puedes dejarme tus comentarios o preguntas al final del artículo, en Twitter o por mail. Hasta la próxima.

Publicado por Roberto Carrancio en Rendimiento, SQL Server, 1 comentario

Parametrización Forzada en SQL Server

Hoy te voy a hablar de una opción muy interesante que puede mejorar el rendimiento de tus consultas: la parametrización forzada. ¿Qué es esto y cómo funciona? Te lo explico en este artículo.

Como ya sabes, si has leído mis artículos anteriores sobre planes de ejecución, caché de planes y optimización para consultas ad hoc, SQL Server genera un plan de ejecución óptimo para cada consulta que recibe, basándose en las estadísticas, los índices y otros factores. Este plan se almacena en la caché de planes para reutilizarlo si se vuelve a ejecutar la misma consulta. Sin embargo, hay casos en los que la misma consulta puede tener diferentes valores de parámetros, lo que hace que el plan óptimo varíe. Por ejemplo, si tenemos una consulta que busca los clientes de una ciudad determinada, el plan óptimo puede cambiar según la ciudad que se especifique.

¿Qué es la parametrización?

En estos casos, SQL Server tiene dos opciones: generar un nuevo plan para cada valor de parámetro diferente (lo que se llama parametrización simple) o generar un plan genérico que sirva para todos los valores posibles (lo que se llama parametrización forzada). La primera opción tiene la ventaja de que el plan se adapta al valor concreto, pero tiene el inconveniente de que consume más recursos y puede llenar la caché de planes con planes similares. La segunda opción tiene la ventaja de que ahorra recursos y evita la fragmentación de la caché de planes, pero tiene el inconveniente de que el plan puede no ser el más adecuado para algunos valores.

¿Qué es la parametrización forzada?

La parametrización forzada hace que SQL Server trate todas las consultas como si fueran procedimientos almacenados con parámetros, y genera un plan genérico para cada consulta, independientemente del valor de los parámetros. Esto puede mejorar el rendimiento en algunos casos, pero también puede empeorarlo en otros. Por eso hay que tener cuidado al usar esta opción y hacer pruebas antes de aplicarla en un entorno productivo.

¿Es mejor la parametrización forzada?

Entonces, ¿cuál es la mejor opción? Depende. No hay una respuesta única, sino que depende del tipo de consultas, de la distribución de los datos, del tamaño de la base de datos y de otros factores. Lo ideal sería poder elegir la opción más conveniente para cada consulta, pero eso no es posible con la parametrización simple. Por eso existe la parametrización forzada, que nos permite activar esta opción a nivel de base de datos o a nivel de consulta individual, mediante una directiva o una sugerencia (HINT).

¿Cuándo activar la parametrización forzada?

Hemos visto que la parametrización forzada puede ayudarnos a reducir recursos al reutilizar los planes de ejecución de las consultas aunque cambien los parámetros. Imagina que tenemos una base de datos que da servicio a una aplicación web con miles o millones de usuarios lanzando la misma consulta, cada uno para sus datos. Esto nos va a generar miles de millones de planes de ejecución, en su mayoría iguales que van a consumir recursos para generarse teniendo ya otro igual guardado y que van a llenar la caché.

Sin embargo esto puede perjudicar mucho el rendimiento si la distribución de nuestros datos no es uniforme. Pero no todo está perdido, a partir de SQL 2019, con los joins dinámicos este problema se reduce en gran medida. 

¿Cómo activo la parametrización forzada?

Si llegado a este punto crees que esta solución es para ti, has detectado muchas recompilaciones que están llenando tu caché, has visto que tus consultas invierten mucho tiempo en compilar planes o simplemente quieres hacer pruebas vamos a ver como activarlo. Como hemos dicho además de con un HINT en cada consulta podemos activar la parametrización forzada por base de datos. Podremos hacerlo desde SSMS, en la pestaña opciones de las propiedades de nuestra base de datos o con el siguiente script:

Una vez habilitado, debería bajar el consumo de CPU de nuestro SQL, si, por el contrario, no es así deberás volver atrás y pensar en otras soluciones como la optimización para consultas Ad Hoc o analizar más a fondo con Query Store tus planes de ejecución.

Conclusión

En este artículo te he explicado qué es la parametrización forzada y cómo funciona. También te he mostrado las ventajas y los inconvenientes de esta opción y cómo puedes activarla o desactivarla según tus necesidades. Espero que te haya resultado útil y que lo pongas en práctica. Recuerda que puedes dejarme tus comentarios o preguntas al final del artículo, en Twitter o por mail. Hasta la próxima.

Publicado por Roberto Carrancio en Rendimiento, SQL Server, 2 comentarios

Optimizando SQL Server para consultas Ad Hoc

En este artículo vamos a hablar de una opción de SQL Server que puede mejorar el rendimiento de las consultas ad hoc, es decir, aquellas que se generan dinámicamente y no se repiten con frecuencia. Se trata de la opción OPTIMIZE FOR AD HOC WORKLOADS, que modifica el comportamiento del caché de planes de ejecución. El objetivo de esto es reducir el consumo de recursos de nuestro servidor como vamos a ver a continuación.

Antes de optimizar para Ad Hoc

Para poder saber si esta es una solución ideal para nosotros tenemos que tener claro una serie de conceptos previos. Estos son los planes de ejecución y la caché de planes. Nosotros los hemos tratado ya en los anteriores artículos en el blog pero aún así vamos a revisarlos.

Como sabemos, los planes de ejecución son la forma en la que el motor de base de datos ejecuta las consultas. Son una guía paso a paso dividida en componentes atómicos que dicen todo lo que va a necesitar hacer SQL Server para devolvernos los datos solicitados.

Como también sabemos, la caché de planes de ejecución es una estructura de memoria que almacena los planes generados por el optimizador para las consultas que se ejecutan en el servidor. Esto permite reutilizar los planes y ahorrar el coste de generarlos cada vez que se ejecuta una consulta. Sin embargo, la caché de planes tiene un tamaño limitado y puede llenarse rápidamente si se ejecutan muchas consultas diferentes. En ese caso, el servidor tiene que eliminar los planes más antiguos o menos usados para hacer espacio a los nuevos, lo que se conoce como recompilaciones. Las recompilaciones pueden afectar al rendimiento del servidor y consumir recursos de CPU y memoria.

Activar la optimización para consultas Ad Hoc

La opción OPTIMIZE FOR AD HOC WORKLOADS ayuda a reducir el impacto de las consultas ad hoc en la caché de planes. Lo que hace es almacenar solamente una parte del plan (un stub) la primera vez que se ejecuta una consulta ad hoc, en lugar del plan completo. Esto ocupa menos espacio en la caché y permite almacenar más planes. Si la consulta se vuelve a ejecutar, entonces se almacena el plan completo y se puede reutilizar. De esta forma, se evita llenar la caché con planes que solo se usan una vez y se favorece la reutilización de los planes que se repiten.

Para activar esta opción, se puede usar el siguiente comando a nivel de base de datos:

Esta opción solo afecta a la base de datos actual y se puede activar o desactivar en cualquier momento. Sin embargo, también existe la posibilidad de configurar esta opción a nivel de instancia, lo que afecta a todas las bases de datos del servidor. Para ello, se puede usar el siguiente comando:

Al activar esta opción a nivel de instancia, podemos aplicar los beneficios de la optimización para consultas ad hoc a todo el servidor, sin tener que hacerlo individualmente para cada base de datos. Esto puede ser útil cuando tenemos un entorno con muchas bases de datos y muchas consultas dinámicas.

¿Merece la pena activar la optimización para Ad Hoc?

Ahora bien, ¿cuándo debemos activar esta opción y cuándo no? La respuesta depende del tipo de carga de trabajo que tengamos en nuestro servidor. Si tenemos un entorno con pocas consultas ad hoc y muchas consultas repetitivas, entonces no es necesario activar esta opción, ya que no tendremos problemas con el caché de planes. Por el contrario, si tenemos un entorno con muchas consultas ad hoc y pocas consultas repetitivas, entonces sí es conveniente activar esta opción, ya que podremos ahorrar espacio en el caché y evitar recompilaciones innecesarias.

Pero ¿cómo saber el número de consultas ad hoc que tenemos en nuestro servidor? Una forma sencilla es usar la vista dinámica de gestión sys.dm_exec_cached_plans, que nos muestra los planes almacenados en el caché. Podemos filtrar por el tipo de objeto ‘Adhoc’ y contar cuánta cache ocupan estos planes. Por ejemplo:

Este comando nos devuelve el espacio consumido por planes ad hoc en la caché. Podemos compararlo con el espacio total de los planes en caché para ver qué porcentaje representan. Si es mayor al 25%, entonces podemos considerar activar la opción OPTIMIZE FOR AD HOC WORKLOADS. Tened en cuenta que los datos de la vista sys.dm_exec_cached_plans se reinician con cada reinicio del servicio de SQL Server por lo que antes de ejecutarlo debemos asegurarnos que el servidor lleva encendido bastante tiempo para tener datos fiables.

Conclusión

En este artículo hemos visto cómo la opción OPTIMIZE FOR AD HOC WORKLOADS puede mejorar el rendimiento de las consultas ad hoc en SQL Server. Como hemos comentado en la introducción también vamos a lograr reducir el consumo de recursos. Esta opción es especialmente útil cuando tenemos un entorno con muchas consultas dinámicas que no se repiten con frecuencia y que pueden llenar el caché de planes rápidamente. Al activar esta opción, podemos reducir el espacio ocupado por los planes en el caché (consumo de memoria RAM), evitar las recompilaciones innecesarias (Consumo de CPU) y favorecer la reutilización de los planes que se ejecutan más de una vez (Consumo de CPU).

Además, hemos visto cómo podemos configurar esta opción a nivel de base de datos o a nivel de instancia, según nuestras necesidades. También hemos visto cómo podemos saber el número de consultas ad hoc que tenemos en nuestro servidor y cuándo debemos activar o no esta opción. Esperamos que este artículo te haya sido útil y te invitamos a leer nuestros artículos anteriores sobre planes de ejecución y caché de planes.

Publicado por Roberto Carrancio en Rendimiento, SQL Server, 0 comentarios

Caché de planes de ejecución en SQL Server

En el artículo anterior, vimos cómo funcionan los planes de ejecución en SQL Server y cómo podemos analizarlos para optimizar nuestras consultas. Hoy vamos a profundizar en un aspecto muy importante de los planes de ejecución: la caché de planes.

La caché de planes es el espacio de memoria donde SQL Server almacena los planes de ejecución que ha generado previamente, para poder reutilizarlos si se vuelve a ejecutar la misma consulta. Esto tiene varias ventajas, como evitar el coste de generar un nuevo plan cada vez, y facilitar el uso de parámetros en las consultas.

¿Cómo ver los planes en caché?

Para ver los planes de ejecución almacenados en caché usaremos la vista de sistema sys.dm_exec_cached_plans y nos ayudaremos de las funciones sys.dm_exec_sql_text y sys.dm_exec_query_plan para ver el texto de la consulta y el plan de ejecución en formato XML. Está será la consulta que usaremos:

¿Cómo se almacenan los planes en caché?

Los más avispados os habréis dado cuenta que el plan de ejecución se almacena usando el campo plan_handle, este corresponde a un hash de la consulta que estamos ejecutando. Esto quiere decir que cualquier mínima variación en el texto de la consulta generará un nuevo plan que se almacenará en la caché, aunque la consulta sea la misma y solo hayamos añadido espacios o tabuladores. Esto puede ser un problema y tenemos que tenerlo en cuenta ya que puede ser que almacenemos multitud de planes en caché para una misma consulta.

¿Qué pasa si la caché se llena y no hay espacio para nuevos planes?

Si la caché se llena, SQL Server empieza a eliminar los planes más antiguos o menos usados, siguiendo un algoritmo llamado LRU (least recently used). Esto puede provocar que se pierdan planes óptimos y que se tengan que generar nuevos planes cada vez, lo que afecta al rendimiento. Para evitarlo, podemos aumentar el tamaño de la caché, usando la opción ‘max server memory’, o podemos limpiar la caché manualmente, usando el comandos DBCC. Tenemos que evitar vaciar completamente la caché en nuestros entornos de producción pues todos las nuevas consultas tendrán que compilar de nuevo sus planes de ejecución consumiendo más recursos. También tendremos que tener en cuenta que al ser una caché en memoria no es persistente, se borrará completamente con cada reinicio del servicio.

¿Puede ser que los planes de la caché no sean los más adecuados para las consultas actuales?

Si los datos han sufrido una variación tal que los planes en caché no son los más adecuados para las consultas actuales, podemos tener un problema de recompilación o de parámetro erróneo. La recompilación ocurre cuando SQL Server detecta que el plan existente no es válido o no es óptimo para la consulta actual, y genera uno nuevo. Esto puede ser beneficioso en algunos casos, pero también puede consumir recursos y tiempo. El parámetro erróneo ocurre cuando SQL Server usa el mismo plan para consultas con diferentes valores de parámetros, lo que puede provocar que el plan no sea eficiente para algunos valores. Para evitar estos problemas, podemos usar la opción ‘optimize for’ o ‘recompile’ en las consultas, o podemos usar procedimientos almacenados con parámetros.

¿Qué pasa si hay demasiados planes similares que ocupan espacio innecesariamente?

Si hay demasiados planes similares que ocupan espacio innecesariamente, podemos tener un problema de crecimiento de la caché. Esto ocurre cuando SQL Server genera planes diferentes para consultas que solo cambian en los valores literales, lo que hace que la caché se llene de planes redundantes. Para evitarlo, podemos usar parámetros en las consultas, o podemos usar la opción ‘forced parameterization’ en las bases de datos.

Uso de procedimientos almacenados para optimizar la caché

Una forma de reducir el impacto de estos problemas es usar procedimientos almacenados en lugar de consultas ad hoc. Los procedimientos almacenados son bloques de código SQL que se almacenan en la base de datos y se pueden ejecutar con diferentes valores de parámetros. 

Los procedimientos almacenados tienen varias ventajas respecto a las consultas ad hoc:
– Solo generan un plan de ejecución por cada procedimiento almacenado, independientemente del valor de los parámetros. Esto evita la inflación de la caché y el parámetro erróneo.
– Solo recompilan el plan si hay cambios en el código del procedimiento almacenado o en la estructura de las tablas. Esto evita la recompilación innecesaria y mejora el rendimiento.
– Permiten encapsular la lógica de negocio y facilitar el mantenimiento y la seguridad del código.

Sin embargo, los procedimientos almacenados también tienen algunos inconvenientes:
– Pueden ser más difíciles de escribir y depurar que las consultas ad hoc.
– Pueden tener problemas de rendimiento si el plan generado no es óptimo para todos los valores posibles de los parámetros. Desde SQL 2019 esto se soluciona en gran medida gracias al uso del componente adaptive join al persistir los planes en caché. En versiones anteriores de SQL tendríamos que recurrir a usar la opción ‘recompile’ o ‘optimize for’ en nuestro procedimiento.
– Pueden tener problemas de seguridad si no se usan correctamente las opciones ‘execute as’ o ‘with encryption’.

Conclusión

La caché de planes es un elemento clave para el rendimiento de SQL Server, ya que permite reutilizar los planes de ejecución y ahorrar recursos. Pero también hay que tener cuidado con los posibles problemas que puede causar, como la pérdida de memoria, los planes ineficientes o la inconsistencia de datos. Para evitarlos, podemos usar herramientas y opciones de configuración que nos permitan controlar y optimizar la caché de planes. Además, podemos usar procedimientos almacenados en lugar de consultas ad hoc, para reducir el número de planes generados y mejorar la calidad del código.

Si quieres convertirte en un experto en planes de ejecución y mejorar el rendimiento de tus bases de datos, no te pierdas los siguientes artículos. Y si tienes alguna duda o comentario, no dudes en escribirme aquí abajo, en Twitter o por mail. Estaré encantado de ayudarte.

Publicado por Roberto Carrancio en Rendimiento, SQL Server, 2 comentarios

Planes de Ejecución en SQL Server

Hoy vamos a hablar de los planes de ejecución en SQL Server, uno de los temas más amplios y a la vez imprescindibles para entender el rendimiento de nuestras consultas. Entender los planes de ejecución es básico para analizar el rendimiento de las consultas y optimizarlas. Empecemos por el principio.

¿Qué son los planes de ejecución? 

Los planes de ejecución son una representación gráfica o textual de cómo SQL Server procesa una consulta. Cada consulta se divide en una serie de operadores lógicos y físicos que realizan diferentes tareas, como leer datos de una tabla, filtrar filas, ordenar resultados, etc. Además, los planes de ejecución nos muestran el orden y el coste de cada operador, así como las estadísticas de las filas procesadas y el uso de memoria y CPU. 

¿Para qué sirven los planes de ejecución? 

Los planes de ejecución nos ayudan a entender cómo SQL Server ejecuta una consulta y a identificar posibles problemas de rendimiento. Por ejemplo, podemos ver si una consulta usa índices adecuados, si hay operadores costosos o ineficientes, si hay estimaciones erróneas de cardinalidad, etc. Con esta información, podemos aplicar técnicas de optimización, como crear o modificar índices, reescribir la consulta, actualizar las estadísticas, etc. 

¿Cómo se obtienen los planes de ejecución? 

Hay varias formas de obtener los planes de ejecución en SQL Server. Una de las más sencillas es usar el Management Studio y activar la opción «Incluir plan de ejecución actual» o «Incluir plan de ejecución estimado» en el menú «Consulta». Esto nos mostrará el plan de ejecución junto con los resultados de la consulta. Otra forma es usar la instrucción SET SHOWPLAN_ON o SET SHOWPLAN_TEXT para obtener el plan de ejecución en formato textual. También podemos usar la función sys.dm_exec_query_plan para obtener el plan de ejecución en formato XML a partir del identificador de una consulta. Después, podemos usar esta web para ver gráficamente nuestros planes en XML.

¿Qué tipos de planes de ejecución hay?

Hay dos tipos principales de planes de ejecución: estimados y actuales. Los planes estimados se generan antes de ejecutar la consulta y se basan en las estadísticas disponibles y en el optimizador de consultas. Los planes actuales se generan después de ejecutar la consulta y reflejan lo que realmente ha ocurrido durante la ejecución. Nuestros planes estimados y actuales pueden ser diferentes si hay cambios en los datos, en las estadísticas o en el entorno. Por eso, es recomendable comparar ambos tipos de planes para detectar discrepancias y ajustar la consulta o las estadísticas si es necesario. 

¿Qué elementos componen un plan de ejecución? 

Un plan de ejecución se compone de varios elementos que representan los operadores lógicos y físicos que intervienen en la consulta. Cada elemento tiene un icono, un nombre y unas propiedades que describen su función y su coste. 

Algunos elementos comunes son: 
– Scan: lee todas las filas o páginas de una tabla o un índice. 
– Seek: busca una fila o un rango de filas en un índice usando una clave. 
– Join: combina filas de dos orígenes usando un criterio de unión. Hay varios tipos de join, como nested loops, merge o hash. 
– Aggregate: agrupa filas por una o más columnas y calcula funciones agregadas, como sum, count o avg. 
– Sort: ordena filas por una o más columnas. 
– Filter: elimina filas que no cumplen una condición. 
– Compute Scalar: calcula una expresión escalar, como una columna calculada o una función. 
– Stream Aggregate: agrupa filas por una o más columnas y calcula funciones agregadas usando un algoritmo eficiente que requiere que las filas estén ordenadas previamente. 
– Hash Match: realiza operaciones como join, aggregate o union usando una estructura hash para almacenar y buscar las filas. 
– Spool: almacena temporalmente las filas en el disco para reutilizarlas más adelante. 
– Top: devuelve un número fijo o porcentual de filas ordenadas por una o más columnas. 

Estos son solo algunos ejemplos, sin embargo, hay muchos más elementos que pueden aparecer en un plan de ejecución. Lo importante es entender qué hace cada elemento y cómo afecta al rendimiento de la consulta. Puedes encontrar la lista completa de operadores en la documentación oficial.

¿Cómo se interpreta un plan de ejecución? 

Para interpretar un plan de ejecución hay que tener en cuenta varios aspectos, como el orden, el coste, las estadísticas y las advertencias.
El orden indica la secuencia en la que se ejecutan los operadores. En un plan de ejecución gráfico, el orden se lee de derecha a izquierda y de arriba a abajo.
Por otro lado, el coste indica el porcentaje de recursos que consume cada operador respecto al total de la consulta y se puede ver en la barra de colores que acompaña a cada elemento. El coste es una estimación basada en las estadísticas y puede no reflejar el coste real.
Las estadísticas muestran información sobre las filas procesadas, el uso de memoria y CPU, el tiempo de ejecución, etc y se pueden ver en las propiedades de cada elemento o en el panel de detalles. Las estadísticas son datos reales que se obtienen al ejecutar la consulta.
Por último, las advertencias son mensajes que indican posibles problemas de rendimiento o de calidad de los datos. 

Advertencias

Las advertencias se pueden ver como símbolos de exclamación o de información en los elementos del plan. Como hemos visto, es importante que les prestemos atención ya que nos indican problemas en nuestras consultas.

Algunas advertencias comunes son: 
– Missing Index: indica que la consulta podría beneficiarse de un índice que no existe. 
– Sort Warnings: indica que la operación de ordenación ha usado más memoria de la disponible y ha tenido que escribir datos en el disco. 
– Hash Warnings: indica que la operación hash ha usado más memoria de la disponible y ha tenido que escribir datos en el disco. 
– Plan Affecting Convert: indica que hay una conversión implícita o explícita de tipos de datos que puede afectar al rendimiento o a la precisión de la consulta.
– SpillToTempDb: indica que una operación ha usado más memoria de la estimada y ha tenido que escribir datos en el disco. 

Estos son solo algunos ejemplos pero, hay muchas más advertencias que pueden aparecer en un plan de ejecución. Lo importante es prestar atención a las advertencias y corregir los problemas si es posible. 

Conclusión 

Los planes de ejecución son una herramienta imprescindible para cualquier DBA que quiera optimizar el rendimiento de las consultas en SQL Server. Los planes de ejecución nos permiten ver cómo SQL Server procesa una consulta y qué recursos consume cada operador. Con esta información, podemos identificar y resolver los problemas más comunes, como el uso inadecuado o la falta de índices, las estimaciones erróneas de cardinalidad, los operadores costosos o ineficientes, etc. Espero que este artículo os haya servido para introduciros en el mundo de los planes de ejecución y os anime a usarlos en vuestro trabajo diario. 

Si queréis profundizar más en este tema, os recomiendo los siguientes recursos:
– Los libros SQL Server Execution Plans y SQL Server Query Performance Tuning de Grant Fritchey
– Los post de Paul White en SQLPerformance.com
– Los cursos de Brent Ozar

Publicado por Roberto Carrancio en Rendimiento, SQL Server, 6 comentarios
VISTAS INDEXADAS DE SQL SERVER

VISTAS INDEXADAS DE SQL SERVER

Las vistas son tablas virtuales que nos devuelven datos de una consulta sobre una o varias tablas. Igual que una tabla tiene sus columnas y sus filas pero al contrario que estas ese conjunto de datos como tal no está almacenado en ningún sitio. Cada tabla tiene sus datos y la vista los lee de ahí. Entonces, ¿los resultados de datos de las vistas no se guardan en ningún sitio? En realidad hay algunos tipos de vistas que sí guardan los datos finales como es el caso de las vistas materializadas que implementan algunos gestores de bases de datos (Oracle, por ejemplo). En el caso de SQL Server este tipo de vista no está disponible, aunque no podemos descartar que se implemente en un futuro (en Azure Synapse Analytics han existido desde siempre).

¿Qué alternativa tenemos en SQL Server?

Como hemos visto antes, las vistas las vemos como si fueran una tabla pero en realidad no tienen datos, los recuperan dinámicamente de las tablas a las que se referencia. Esto es muy útil en la mayoría de los casos ya sea por simplicidad de las consultas, para abstraernos de la estructura original y simplificar la estructura saliente o para gestionar permisos. Sin embargo el uso de una vista no afecta en nada al rendimiento pues ejecuta la consulta tal cual como si la escribiéramos a mano. Si una vista lee sobre varias tablas grandes generará mucho consumo de E/S y si la definición de la vista incluye procesamientos complejos y muchas uniones entre tablas tendremos una notoria degradación de rendimiento.

Como alternativa, en SQL Server podemos hacer uso de un tipo de vista especial que son las Vistas Indexadas (o indizadas), son vistas que tienen un índice clustered por lo que si van a almacenar el conjunto de resultados en la base de datos para poder hacer una lectura plana.

Dónde usar las vistas indexadas

Las vistas indexadas ofrecen un rendimiento de lecturas mejorado al hacer uso del índice para leer los datos y no tener que ejecutar la consulta subyacente. Sin embargo, nos pueden llegar a penalizar considerablemente las operaciones de escritura al añadir no sólo otro índice donde escribir los datos sino complejidad a ese índice. Adicionalmente podremos crear tantos índices nonclustered sobre la vista como necesitemos. Al igual que ocurre con los índices de las tablas en nuestra mano queda medir el coste/beneficio y valorar su idoneidad.

Con las vistas indexadas notaremos una mejora sustancial en el rendimiento de nuestras consultas si las aplicamos sobre entornos con una gran diferencia de lecturas frente a escrituras, se me viene a la cabeza sobre todo entornos Data Warehouse, bases de datos OLAP o entornos de minería de datos. Rara vez serán recomendables en entornos con alta carga de transacciones IUD (insert, update y delete) en bases de datos OLTP.

Limitaciones de las vistas indexadas

Como ya hemos visto uno de los inconvenientes de las vistas indexadas es que la degradación en rendimiento de las escrituras es mayor que la mejora en las lecturas, esto nos limita en gran medida su uso. Sin embargo no es su única limitación, la verdad es que tienen una amplia lista de incompatibilidades y requisitos. Uno de los principales requisitos de las vistas indexadas es que hay que crearlas con la opción SCHEMABINDING esto implica que no se podrán modificar las tablas referenciadas.

Consideraciones para crear vistas indexadas

Además de tener que crear la vista como SCHEMABINDING tenemos que tener en cuenta otros aspectos importantes:

  • Las vistas indexadas no admiten expresiones no deterministas. Es decir, las expresiones de la vista siempre deben devolver el mismo resultado no como GETDATE() que nos devolvería un valor distinto en cada ejecución.
  • Las tablas y funciones dentro de la vista deben declararse con el nombre completo (esquema.tabla).
  • No se admiten subconsultas.
  • No se admiten OUTER JOINS, esto deja fuera RIGHT JOIN y LEFT JOIN.
  • El índice clustered de nuestra vista ocupará espacio en disco.
  • Solo se puede hacer referencia a tablas de la misma base de datos.
  • Si tenemos GROUP BY, la definición de la vista debe contener COUNT_BIG(*), pero no HAVING.
  • No se puede usar EXISTS, NOT EXISTS, COUNT(*), MIN, MAX, hints de tablas, TOP ni UNION.
  • No puede utilizar los tipos de datos text,  ntext ,  image o  XML. El tipo de datos float se puede utilizar en la vista, pero no en el índice agrupado

Como crear vistas indexadas

Para crear una vista indexada lo primero que haremos será crear la vista con la opción SCHEMABINDING 

Una vez que tenemos creada la vista tendremos que crear el índice clustered.

En este punto el optimizador de consultas podrá usar nuestro índice para cualquier consulta sobre la tabla, incluso para consultas sobre las tablas sin que se use la vista aunque, esto último, sólo en ediciones Enterprise de SQL Server.

Conclusiones

Un gran poder conlleva una gran responsabilidad y las vistas indexadas son una increíble herramienta en entornos o tablas con gran cantidad de lectura y pocas modificaciones pero si no es así nos pueden hacer mucho daño al servidor. El uso de vistas indexadas de SQL Server puede ser una buena técnica para mejorar el rendimiento de las consultas al reducir el costo de E/S y la duración de las consultas, pero requiere pruebas, planificación y un estudio pormenorizado de donde usar vistas indexadas. Se debe realizar un análisis completo del impacto en el rendimiento, midiendo las mejoras en el rendimiento de lecturas frente al coste en las escrituras.

Publicado por Roberto Carrancio en Rendimiento, SQL Server, 4 comentarios