SQL Server

Active Directory (AD) para DBAs de SQL Server

En el mundo de la administración de bases de datos, el conocimiento técnico es la base para cualquier DBA y cuanto mayor conocimiento sobre el SGBD con el que trabajamos mejor podremos desempeñar nuestro trabajo. Pero, ¿qué pasa con los sistemas y servicios que interactúan directamente con nuestras bases de datos? Aquí es donde entra en juego, por ejemplo, el Active Directory (AD), una pieza clave en la infraestructura de cualquier organización y que si utilizamos SQL Server tendremos que integrar en nuestro dia a dia. Comprender cómo AD y los sistemas operativos se entrelazan con SQL Server no solo es deseable, sino esencial para un desempeño experto y seguro.

¿Qué es AD y por qué es importante para los DBAs?

Active Directory (AD) es un directorio de servicios centralizado que gestiona las identidades y las relaciones de seguridad dentro de una red. Por identidades nos referimos a los objetos de nuestra organización, desde cuentas de usuario y servicios hasta máquinas cliente y servidores. Estas entidades se organizan en base a su pertenencia a grupos de seguridad y entidades organizativas sobre las que, posteriormente, podremos gestionar los permisos.

Para un DBA, entender los principios de AD es crucial, ya que SQL Server se integra completamente con este servicio para la autenticación y autorización de usuarios. Un dominio de AD bien configurado garantiza que solo los usuarios autorizados tengan acceso a los datos sensibles, manteniendo la integridad y la seguridad de la información. Además el hecho de poder gestionar grupos de seguridad nos va simplificar mucho la tarea de asignar permisos a los usuarios y su posterior mantenimiento.

Conceptos básicos de AD para DBAs

Aunque como DBAs no es parte de nuestras responsabilidades administrar el directorio activo (AD), es importante que estemos familiarizados con sus conceptos ya que, como hemos visto, están directamente relacionados con la gestión de la seguridad de nuestras bases de datos.

Dominios de AD

Un dominio es una unidad lógica de organización en un Directorio Activo. Cada dominio tiene una base de datos de seguridad que almacena información de seguridad sobre objetos como usuarios, grupos y equipos. Como ya hemos visto, que nuestro SQL Server sea parte del dominio nos facilita una administración centralita de usuarios y políticas de seguridad.

Controladores de Dominio (DC)

Un Controlador de Dominio (DC) es un servidor que responde a solicitudes de autenticación y mantiene el directorio de dominio. Los DC son responsables de permitir el acceso a los recursos de red y de aplicar las políticas de seguridad del dominio. SQL Server puede delegar en el controlador de dominio la gestión de usuarios mejorando la seguridad y facilitandonos la administración.

Unidades Organizativas (OU)

Las Unidades Organizativas (OU) son contenedores dentro de un dominio que pueden contener usuarios, grupos, equipos y otras OU. Las OU se utilizan para organizar y administrar objetos dentro de un dominio. Por nuestra parte, tenemos que saber que podemos agrupar servidores y/o usuarios en OU para centralizar ciertas tareas de administración.

Protocolos de Autenticación (Kerberos y NTLM)

Kerberos y NTLM son protocolos de autenticación utilizados por los DC para verificar la identidad de los usuarios. Kerberos es un protocolo basado en tickets, mientras que NTLM utiliza un desafío-respuesta. SQL Server está preparado para trabajar con ambos protocolos garantizando un acceso seguro a los datos.

Usuarios y Grupos de AD

Los usuarios son cuentas que representan a individuos o servicios en la red. Los grupos son colecciones de usuarios que comparten los mismos derechos de acceso a los recursos. Como ya hemos comentado, SQL Server se aprovecha de esta capacidad para la autenticación y autorización de usuarios. Gracias a los grupos, podremos gestionar accesos de varios usuarios a recursos de manera simultánea.

Nombre Principal de Servicio (SPN)

El Nombre Principal de Servicio (SPN) es un identificador único asignado a cada servicio que se ejecuta en un servidor. Los SPN se utilizan en la autenticación Kerberos para asociar un servicio con una cuenta de servicio. Para que SQL funcione con Kerberos deberemos registrar el SPN para la cuenta de servicio de SQL Server.

Políticas de Seguridad (GPO)

Las Políticas de Grupo (GPO) son reglas que se pueden aplicar a usuarios o equipos dentro de un dominio. Las GPO se utilizan para controlar el entorno de trabajo de los usuarios y los equipos. Es muy común que SQL Server se beneficie de las GPO de longitud y complejidad de contraseñas, por ejemplo.

Confianzas

Las confianzas son relaciones que permiten a los usuarios de un dominio acceder a recursos en otro dominio. Como DBAs esto nos va a ahorrar mucho trabajo al no necesitar duplicar usuarios.

Catálogo Global de AD

El Catálogo Global es una base de datos distribuida que contiene una copia parcial de todas las bases de datos de dominio en un bosque. Se utiliza para acelerar las consultas dentro del bosque. Tenemos que saber que tanto nuestros servidores como los usuarios pertenecen a este catálogo global.

Bosque

Un bosque es una colección de uno o más dominios de Directorio Activo que comparten un esquema común. Esto nos va a permitir gestionar varios SQL Server de diferentes dominios bajo una configuración global.

Esquema

El esquema es la definición de todos los objetos y atributos que se pueden crear en el Directorio Activo. Nuestros SQL Server serán capaces de gestionar las extensiones de los esquemas y nos permitirán llevar a cabo configuraciones especializadas o cuando necesitemos cumplir con ciertos requisitos de integración.

Protocolo Ligero de Acceso a Directorios (LDAP)

LDAP es un protocolo de red utilizado para acceder y gestionar el Directorio Activo. LDAP permite a los clientes buscar y manipular entradas en el directorio. SQL Server utiliza LDAP para acceder en modo consulta a la información de AD y así validar las credenciales de usuarios o la pertenencia a grupos.

Conclusión

En este post hemos podido adentrarnos en los conceptos básicos de AD, sin embargo os recomiendo profundizar y probar. Para muchas cosas necesitaréis la ayuda del administrador de directorio activo de vuestra organización pero a la larga lo vais a agradecer. Ser un DBA de SQL Server con conocimientos avanzados en AD y sistemas no solo mejora la seguridad y la eficiencia de nuestros servidores, sino que también elevará nuestro valor profesional en el mercado. La integración de estos conocimientos permite enfrentar desafíos complejos y asegurar que las bases de datos sean confiables, seguras y tengan un buen desempeño. Nosotros, como expertos en la materia, debemos estar siempre al tanto de las últimas tendencias y mejores prácticas para garantizar la excelencia operativa en un entorno de alta criticidad.

Espero que este artículo te haya sido útil y que te ayude a tener mayor control sobre tus servidores SQL Server. Te animo a investigar más y definir nuevas alertas que puedan resultarte interesantes. Una vez hecho, puedes dejarlo en los comentarios y, entre todos, seguro que aprendemos algo nuevo. Si tenéis alguna duda o sugerencia, podéis dejarla en Twitter, por mail o dejarnos un mensaje en los comentarios. Y recuerda que también tenemos un grupo de LinkedIn y un canal de YouTube a los que te puede unir. ¡Hasta la próxima!

Publicado por Roberto Carrancio en SQL Server, 0 comentarios

Monitorización con Alertas del Agente en SQL Server

Llegan las vacaciones de semana santa y a todos nos gusta desconectar. Aun así, no debemos descuidar la vigilancia sobre nuestros servidores, sobre todo los más críticos. En el mundo de la informática en general y, de la administración de bases de datos en particular, estar al tanto de lo que sucede en nuestros sistemas es crucial. Una actuación sencilla a tiempo nos puede ahorrar una larga intervención para corregir una incidencia en un futuro. Es por esto que la monitorización nativa de SQL Server a través de las alertas del agente es un aliado fundamental de cualquier DBA. En el mercado existen multitud de herramientas que ofrecen una ventana directa al rendimiento y la salud de nuestras bases de datos pero suelen ser costosas y complejas de implementar, mientras que las alertas de SQL, sin ser la solución definitiva, nos brindan una excelente solución básica pero efectiva.

¿Qué son las Alertas del Agente?

Las alertas del agente son un conjunto de respuestas automatizadas que se activan ante eventos específicos en SQL Server. Estos eventos pueden ser desde un simple rendimiento subóptimo hasta errores críticos que requieren atención inmediata. Este sistema de monitorización vigila nuestro SQL Server en busca de los desencadenadores que hayamos definido y, gracias al correo electrónico de base de datos es capaz de hacernos llegar el aviso.

También dispondremos de una opción para ejecutar automáticamente un job que nos será muy útil en caso de tener automatizado un procedimiento de resolución automático para ciertos eventos controlados.

Monitorización con alertas de SQL Server

La monitorización nativa utiliza herramientas integradas en SQL Server para mantener un ojo vigilante sobre los procesos críticos. Esto incluye el seguimiento de bloqueos, la supervisión del rendimiento de las consultas y la detección temprana de posibles problemas. 

Configuración Óptima para DBAs

Si estamos familiarizados con o tenemos cierta experiencia en SQL Server, configurar alertas del agente es un proceso familiar y sencillo. Sin embargo, es importante ajustar bien los parámetros que las desencadenan para que las alertas sean significativas y proporcionen información valiosa sin saturarnos con falsos positivos. Un exceso de alertas puede llegar a ser igual a no tener alertas ya que corremos el riesgo de terminar perdiendo información sobre incidentes graves entre tanto aviso. 

Caso práctico de configuración de alertas

Las alertas en SQL Server se pueden configurar tanto desde la interfaz gráfica como por script. En el caso de la interfaz gráfica, lo encontraremos colgando del agente de SQL Server en nuestro Management Studio. La ventana de configuración de las alertas tiene este aspecto:

Como veis tenemos un apartado general en el que definiremos el nombre de nuestra alerta y cuál será su desencadenante. Para el tipo “SQL Server error alert”, que es el que más nos interesa, podremos decidir si afecta a una base de datos en concreto o a todas y si se activará por un número de error específico o por todos los que respondan a un nivel de gravedad. También podemos añadir un filtro extra por texto del mensaje. Existen otros tipos de alerta por condiciones de rendimiento o por eventos WMI de Windows. Disponemos también de otros dos apartados en los que configurar la respuesta a estas alertas y sus opciones.

Qué errores monitorizar con alertas

Para poder configurar alertas en base a errores de SQL Server es imprescindible conocer el significado de los niveles de gravedad. Estos niveles van desde el 0 hasta el 25 y se dividen de la siguiente manera. Del 0 al 10 representan mensajes informativos sobre el estado del servidor. Del 11 al 16 son errores que pueden ser corregidos por los usuarios como que un objeto no existe o código SQL mal escrito por ejemplo. A partir de la gravedad 17 si que requerirán nuestra intervención como DBAs y son estos los que os recomiendo monitorizar.

  • Gravedad 17 a 19: Indica errores de software que no pueden ser corregidos por el usuario. Como falta de recursos para completar una consulta.
  • Gravedad 20 a 24: Indica problemas del sistema y son errores irrecuperables, lo que significa que ya no está en ejecución la tarea del motor de base de datos que esté ejecutando una instrucción o lote.
  • Gravedad 25: Error desconocido, aquí irá todo error no controlado por el motor de base de datos.

Además de los errores basados en gravedad yo monitorizo también los códigos de error específicos 823, 824 y 825 que alertan de falta de espacio en disco y el código 1480 que indica un cambio de rol del Always On

¿Os parecen muchas cosas? No os preocupéis, os dejo aquí el script para crear directamente estas alertas:

Conclusión

Con una configuración adecuada y un uso correcto de las alertas del agente, podemos asegurar que nuestros sistemas de bases de datos operen con la máxima eficiencia. La monitorización nativa no es solo una herramienta, es una parte integral de nuestra estrategia proactiva para mantener la salud de SQL Server. Es cierto que, al usar una monitorización en local, se nos escaparán eventos más graves como la caída del propio servidor pero es un buen punto de partida y, sobre todo, es mejor que no tener nada.

Espero que este artículo te haya sido útil y que te ayude a tener mayor control sobre tus servidores SQL Server. Te animo a investigar más y definir nuevas alertas que puedan resultarte interesantes. Una vez hecho, puedes dejarlo en los comentarios y, entre todos, seguro que aprendemos algo nuevo. Si tenéis alguna duda o sugerencia, podéis dejarla en Twitter, por mail o dejarnos un mensaje en los comentarios. Y recuerda que también tenemos un grupo de LinkedIn y un canal de YouTube a los que te puede unir. ¡Hasta la próxima!

Publicado por Roberto Carrancio en SQL Server, 2 comentarios

VLF: Entendiendo el Log de SQL Server nivel pro

En nuestra constante búsqueda de optimización y eficiencia en el manejo de bases de datos, nos encontramos con una pieza clave en el rompecabezas de SQL Server: los Virtual Log Files (VLF). Estos componentes, aunque pequeños y a menudo pasados por alto, son fundamentales para el rendimiento y la gestión de nuestras bases de datos. Hoy, nos sumergimos en el mundo de los VLF para entender su función y cómo una gestión adecuada puede marcar la diferencia en nuestro trabajo diario como DBAs. Referenciando nuestro artículo anterior ¿Cómo funcionan los ficheros de Log de SQL Server?, podemos recordar que el log de transacciones juega un papel vital en la recuperación de datos y, los VLFs, como parte fundamental de los logs, tienen la misma importancia.

¿Qué son los VLF y por qué son importantes?

Los VLF son segmentos virtuales en los que se divide el archivo de log de transacciones de una base de datos en SQL Server. Es decir, SQL Server no trabaja con el fichero de log completo sino con pequeñas particiones del mismo. Cada vez que se crea o se expande un log, SQL Server lo divide en varios VLFs. La cantidad y el tamaño de estos VLF pueden tener un impacto significativo en el rendimiento de la base de datos, especialmente durante operaciones de recuperación y respaldo. En casos extremos, si tenemos el log muy particionado puede afectarnos también al rendimiento de nuestras transacciones. 

Gestión Efectiva de VLF

Para mantener un sistema saludable, es crucial gestionar adecuadamente los VLF. Un número excesivo de VLF pequeños puede causar lentitud en el proceso de recuperación de la base de datos, mientras que muy pocos VLF grandes pueden dificultar el proceso de respaldo. Por ello, encontrar el equilibrio correcto es esencial. Los VLF son los bloques de construcción de este log, y su gestión eficiente permite una recuperación más rápida y una mejor disponibilidad de la base de datos.

Una estrategia efectiva para la gestión de VLF implica monitorear su cantidad y tamaño regularmente. SQL Server proporciona herramientas que nos permiten visualizar y ajustar estos parámetros, como el deprecado comando DBCC LOGINFO o su nueva versión, la función sys.dm_db_log_info. Además, prácticas como el truncamiento regular del log y la expansión controlada del archivo de log ayudan a mantener un número óptimo de VLF.

Creación de VLFs

Hemos visto que el motor de SQL Server crea automáticamente los VLFs durante el crecimiento de los ficheros de logs, sin embargo, esto no significa que nosotros no podamos influir sobre ello. Simplemente tendremos que conocer qué reglas sigue SQL para crear VLFs para adaptarnos a ello. Antes de nada tenemos que especificar que las reglas de creación de VLFs han cambiado con SQL 2022 por lo que tanto para esta versión como para Azure tendremos que tenerlo en cuenta. Veamos cómo se crean los VLFs:

  • Cuando el crecimiento del archivo de log es menor a 64 Mb SQL creará 4 VLFs en versiones antiguas y solo 1 VLF en SQL 2022 y en Azure.
  • Si el crecimiento del archivo de log es igual o mayor a 64 Mb pero menor a 1 Gb se crearán 8 VLFs.
  • Si el crecimiento del archivo de log es igual o mayor a 1Gb se crearán 16 VLFs.

Cuantos VLFs tienen mis logs

Ya sabemos cómo se crean los VLFs y por qué podemos llegar a tener muchos en nuestros mecheros de logs pero, no os he dicho aún cómo comprobar en vuestras bases de datos cuantos VLFs teneis. Para ello usaremos el siguiente script. Y ahora la pregunta clave, ¿Cuántos VLF debería tener? La respuesta es depende, no hay una respuesta universal a esta pregunta. Personalmente creo que sobre 50 es una buena cifra pero dependerá en gran medida del tamaño del fichero de log. 

Hora de hacer números y corregir los VLF

Supongamos que nuestra base de datos tiene un log de 20Gb y hemos visto que por alguna mala práctica del pasado tenemos muchos VLF. Lo primero que tendremos que hacer es un shrink para reducir el log lo máximo posible. Una vez con el log en su tamaño mínimo vamos a volver a dimensionarlo a sus 20Gb originales pero siguiendo las buenas prácticas de VLF. Vamos a crear un número de VLF cercano a 50. Para ello no podemos dimensionar directamente en 20Gb porque solo nos crearía 16 VLF y serían muy grandes para ser administrados por SQL de manera óptima. Qué pasa si aumentamos 8 Gb iniciales, luego otros 8 y terminamos con un crecimiento de 4 Gb. Esto serían 3 crecimientos del fichero superiores a 1 Gb por lo que se nos crearían 16 VLF en cada “salto”, 16*3=48. Parece bastante razonable. Ahora, si el fichero puede necesitar crecer en un futuro, podría ser interesante hacer 3 crecimientos de 8 Gb lo que nos daría 24 Gb de log repartidos igualmente en 48 VLF (unos ficheros de 512 Mb cada uno, algo asumible).

Conclusión

La gestión de VLF no es solo una tarea de mantenimiento; es una oportunidad para maximizar el rendimiento de nuestras bases de datos. Al comprender la importancia de estos elementos y aplicar prácticas de gestión efectivas, podemos asegurar un sistema robusto y ágil. Los VLF son, sin duda, pequeños gigantes en el mundo de SQL Server, y su correcta administración está reservada a unos pocos DBAs expertos con gran pericia técnica, como vosotros ahora.

Espero que este artículo te haya sido útil. Si tenéis alguna duda o sugerencia, podéis dejarla en Twitter, por mail o dejarnos un mensaje en los comentarios. Y recuerda que también tenemos un grupo de LinkedIn y un canal de YouTube a los que te puede unir. ¡Hasta la próxima!

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

¿Cómo funcionan los ficheros de Log de SQL Server?

En el artículo de hoy vamos a profundizar en los ficheros de log. Estos ficheros representan una de las herramientas más potentes para garantizar la integridad y la recuperación de datos. Estos archivos, a menudo subestimados, son fundamentales para el funcionamiento de cualquier sistema que dependa de la gestión de datos transaccionales como es SQL Server. 

¿Qué son los ficheros de Log?

Los ficheros de log, también conocidos como archivos de transacciones, registran todas las operaciones que modifican los datos o la estructura de la base de datos. Cada transacción en SQL Server comienza con una entrada en el log, asegurando que cualquier cambio pueda ser rastreado y, si es necesario, revertido o reproducido. Físicamente, los podemos encontrar como ficheros con extensión LDF. 

La importancia de los Logs en la recuperación de datos

Como ya vimos en el artículo sobre los CHECKPOINTS, una de las funciones más críticas de los ficheros de log es su papel en la recuperación de datos. En caso de un fallo del sistema, los logs son esenciales para restaurar la base de datos a un punto consistente en el tiempo, minimizando la pérdida de datos y manteniendo la integridad de los datos. Esto, en última instancia, nos garantiza la continuidad de nuestro negocio.

El impacto del nivel de recuperación en el comportamiento de la base de datos

El nivel de recuperación de una base de datos es un factor determinante en la forma en que SQL Server maneja los ficheros de log y, por ende, afecta directamente el comportamiento de la base de datos. Al seleccionar un modelo de recuperación, estamos definiendo cómo y cuándo se registran las transacciones en los ficheros de log, lo que tiene implicaciones significativas en la disponibilidad, la integridad y la recuperabilidad de los datos.

Modelo de recuperación simple

Con el modelo de recuperación simple, SQL Server minimiza el mantenimiento de los ficheros de log al truncar automáticamente los registros de transacciones que ya no son necesarios para la recuperación. Truncar el fichero significa vaciarlo, sin embargo, como ya hemos comentado en más ocasiones, el tamaño del fichero no se reduce, se queda pre dimensionado para cuando otras transacciones lo necesiten. Este modelo de recuperación de las bases de datos reduce el espacio de almacenamiento requerido y simplifica la gestión, pero limita la capacidad de recuperar la base de datos a puntos específicos en el tiempo, ofreciendo solo la posibilidad de restaurar hasta el último respaldo completo o diferencial.

Modelo de recuperación completa

A diferencia del modo simple, el modelo de recuperación completa mantiene un registro detallado de todas las transacciones, lo que permite una recuperación punto a punto. Esto significa que podemos restaurar la base de datos a cualquier momento específico, siempre y cuando dispongamos de los respaldos de log necesarios. Para entendernos, las transacciones no se borran del fichero de log nada más concluyen (commit o rollback) sino que se mantienen en el fichero hasta que se hace una copia de seguridad. Este nivel de detalle, por tanto, requiere una gestión más activa de los ficheros de log para evitar un crecimiento excesivo y problemas de rendimiento.

Modelo de recuperación bulk-logged

El modelo de recuperación bulk-logged es una variante del modelo completo que ofrece una solución intermedia. Permite operaciones masivas de datos, como importaciones o indexaciones, sin registrar cada detalle en el log mientras mantiene todo el detalle de las transacciones normales. Esto nos permite reducir el tamaño del fichero durante estas operaciones. Aunque ofrece ciertas ventajas en términos de rendimiento, también conlleva un riesgo mayor en la recuperación de datos, ya que no se pueden recuperar transacciones individuales realizadas durante las operaciones masivas.

Gestión y mantenimiento de los ficheros de Log

Una gestión efectiva de los ficheros de log implica monitorear su tamaño y realizar un mantenimiento regular, como el truncamiento de log, que libera espacio para nuevas transacciones. Ignorar estas prácticas puede llevar a un crecimiento descontrolado del log y afectar negativamente el rendimiento del sistema. 

Como hemos visto, el log de transacciones almacena las transacciones en curso en el modelo de recuperación simple o, en el modo completo las en curso y las finalizadas de las que no dispongamos backup. Podemos entender entonces que, puede llenarse completamente por varias razones, que van desde un gran número de transacciones hasta consultas mal optimizadas o configuraciones inadecuadas. Uno de los factores más comunes es la retención de registros de transacciones debido a transacciones largas o no completadas. Además, si el modelo de recuperación de la base de datos está configurado como completo o bulk-logged y no se realizan copias de seguridad del log de forma regular, el log seguirá creciendo, ya que SQL Server espera que estos registros estén disponibles para una posible recuperación punto a punto.

¿Por qué no se vacía mi log de transacciones?

SQL Server proporciona una columna muy útil en la vista de catálogo sys.databases llamada log_reuse_wait_desc, que indica la razón por la cual el espacio del log de transacciones no se puede reutilizar. Algunos de los tipos de log_reuse_wait más comunes son:

  1. ACTIVE_TRANSACTION: Indica que hay una transacción activa que impide el truncamiento del log.
  2. LOG_BACKUP: Señala que se necesita una copia de seguridad del log para permitir la reutilización del espacio.
  3. CHECKPOINT: Sugiere que no se ha alcanzado un punto de control que permita el truncamiento del log.
  4. ACTIVE_BACKUP_OR_RESTORE: Implica que una operación de copia de seguridad o restauración está en curso, lo que impide el truncamiento.
  5. REPLICATION: Indica que la replicación no ha terminado de procesar los registros que necesitan ser distribuidos. Este tipo de espera se usa también para Log Shipping.
  6. DATABASE_MIRRORING: Señala que el espejo de base de datos está activo y que los registros aún no se han enviado a la réplica secundaria.
  7. AVAILABILITY_REPLICA: Indica que una réplica de disponibilidad de AlwaysOn está aplicando registros del log a una base de datos secundaria.

Cada uno de estos estados requiere una acción específica para liberar espacio en el log de transacciones. Por ejemplo, si el log_reuse_wait_desc muestra LOG_BACKUP, se debe realizar una copia de seguridad del log para permitir que el espacio sea reutilizado. Si muestra ACTIVE_TRANSACTION, se debe investigar y resolver la transacción larga o bloqueada.

Conclusión

Los ficheros de log son el core de la seguridad y la integridad de las bases de datos en SQL Server. Su correcta gestión y comprensión son esenciales para cualquier DBA que busque asegurar la máxima eficiencia y confiabilidad en sus sistemas. Al dominar los ficheros de log, nos equipamos con una poderosa herramienta para enfrentar casi cualquier desafío en el mundo de las bases de datos.

Entender por qué se llena el log de transacciones y cómo gestionar los diferentes tipos de log_reuse_wait es esencial para cualquier administrador de bases de datos SQL Server. Una gestión adecuada del log no solo previene problemas de rendimiento, sino que también asegura la disponibilidad y la recuperabilidad de la base de datos. Con este conocimiento, los DBAs podemos tomar medidas proactivas para mantener el log de transacciones en un tamaño manejable y garantizar el funcionamiento óptimo de nuestros sistemas de bases de datos.

Espero que este artículo te haya sido útil. Si tenéis alguna duda o sugerencia, podéis dejarla en Twitter, por mail o dejarnos un mensaje en los comentarios. Y recuerda que también tenemos un grupo de LinkedIn y un canal de YouTube a los que te puede unir. ¡Hasta la próxima!

Publicado por Roberto Carrancio en SQL Server, 2 comentarios

Solución a problemas de Parameter Sniffing

Seguimos con el tema de ayer sobre el Parameter Sniffing en SQL Server y, como prometimos, vamos a ver cómo podemos hacer para controlarlo y beneficiarnos de ello minimizando sus inconvenientes. Es este, por tanto, una segunda parte del artículo de ayer que os recomiendo encarecidamente leer antes de continuar con este. Como ya sabemos, si la distribución de nuestros datos es relativamente equitativa, un reaprovechamiento del plan de ejecución de una consulta será muy beneficioso para el rendimiento. De lo contrario, si la distribución de datos tiene gran variación, reutilizar un plan hará que este no sea el óptimo para esa ocasión. 

¿Es malo el parameter sniffing?

Empecemos por el principio, la pregunta que todos os estáis haciendo ¿es malo el parameter sniffing para el rendimiento? Para mi la respuesta es no, aun con todos sus inconvenientes, conociendo su comportamiento podremos beneficiarnos en gran medida de ello. En la mayoría de escenarios OLTP, el comportamiento normal del parameter sniffing mejora el rendimiento de las consultas. Para los escenarios en los que nos encontramos con inconvenientes, normalmente será en algún procedimiento almacenado y no todos y, por suerte, tenemos varias alternativas para solventar el problema.

Identificando el problema del parameter sniffing

El primer paso cuando tenemos un problema es reconocerlo y en esta ocasión será sencillo. Si no tenemos habilitado la parametrización forzada bastará con ejecutar nuestra consulta fuera del procedimiento almacenado para comparar los planes. En otras ocasiones los usuarios nos darán pistas sin quererlo, como cuando unos clientes me decían que tras reiniciar el servidor el procedimiento volvía a funcionar. Reiniciar, por si solo no resuelve nada y si no somos capaces de saber que provocaba el problema antes del reinicio nos volveremos a encontrar en esa misma situación antes o después. Pero esta discusión es para otra ocasión, volvamos a mi anécdota. 

Lo que les pasaba a mis clientes es que si la primera ejecución del plan de la caché era con un parámetro con un volumen de datos muy inferior a la media, el plan cacheado iba a ir mal para todas las siguientes ejecuciones. Como la caché de SQL se vacía al reiniciar y ellos estaban esperando el reinicio para ejecutar el SP con los parámetros que antes daban problemas ya se almacenaba en caché el plan correcto y todo iba bien hasta que por presión de memoria ese plan se borraba y la siguiente ejecución era de un parámetro distinto.

Soluciones al problema del parameter sniffing

Bien, sabemos que el causante de nuestro problema de rendimiento es un problema de parameter sniffing. Ahora tenemos que solucionarlo. Para ello os voy a proponer distintas soluciones.

No cambiar nada

Sabemos lo que está pasando y que es el comportamiento natural de SQL Server, expliquemos todo esto a nuestros usuarios y que se conformen con el resultado. No va a funcionar, ¿verdad?. Habéis soltado una carcajada al leerlo que se ha oído en la luna, que os conozco. Los usuarios de SQL necesitan sus datos y los necesitan rápido y por mucho que nosotros les contemos no se van a conformar. Y están en su derecho así que descartemos este punto y vayamos a por los siguientes. 

Pasa el marrón a otro

La siguiente solución que tengo que poner, pero que, al igual que la anterior, tampoco os recomiendo es pasar la pelota al equipo que desarrolla el código del procedimiento. Podríais explicarles lo que está pasando y que creen un SP distinto para cada parámetro. Como os digo esto es una mala idea, malísima en realidad. Acaba completamente con todas las ventajas de un procedimiento almacenado y ni hablar de si problema si es causado por tener activada la parametrización forzada. Descartemos este punto también por favor.

Actualiza tu SQL

Ya comentamos ayer que el las últimas versiones de SQL Server (a partir de 2019) entran en juego los planes de ejecución con joins adaptativos lo que nos permitirá que pasadas unas ejecuciones se persistirá un plan dinámico en caché con varias alternativas en función de los parámetros. Esto es un avance, sin embargo, aún no lo veo una solución pues necesitas de varias ejecuciones lentas para que SQL se de cuenta de lo que pasa y en un entorno con gran cantidad de consultas donde los planes en caché no duran tanto como nos gustaría puede no ser una solución.

Recompilaciones del procedimiento

En este punto, ya hemos descartado no hacer nada y también crear varios procedimientos almacenados, veamos cómo podemos hacer para que nuestro procedimiento problemático rinda como debería. Una de estas soluciones es crear el procedimiento para que no haga uso de los planes en caché y recompile siempre el plan de ejecución. Esto lo haremos en la declaración del procedimiento con la sugerencia de procedimiento almacenado RECOMPILE. Por ejemplo: 

Con esa simple sugerencia conseguiremos que los planes de ejecución de todas las consultas del procedimiento almacenado se recopilen antes de la ejecución, lo que nos supondrá un mayor coste de CPU pero nos garantizará un plan óptimo. Si es uno o unos pocos procedimientos en los que tenemos problemas al final compensa.

Recompilaciones de las consultas

Si el problema lo estamos teniendo fuera de un procedimiento almacenado por tener habilitada la parametrización forzada o si queremos hilar más fino porque sabemos que solo una de las muchas consultas de un procedimiento es la que tiene problemas podemos hilar más fino y aplicar la sugerencia RECOMPILE a nivel de consulta. Por ejemplo 

En este ejemplo tenemos dos consultas, un select y un insert, sin embargo solo recopilaremos el plan de ejecución de la primera.

Optimizado para valor

Otra de las opciones que tenemos a nivel de consulta es utilizar una sugerencia que indique que calcule el plan de ejecución para un valor concreto y no para el que se pase como parámetro de nuestro SP. En algunas ocasiones puede ser una solución pero a mi no me gusta porque genera planes ultra dimensionados cuando no son necesarios y requiere mucho mantenimiento a medida que los datos cambian. Si recordáis el ejemplo del almacén que vimos ayer es como si desplegamos todos los recursos necesarios para mover maquinaria industrial pesada para al final realmente mover un clavo. Aun así os dejo un ejemplo de cómo sería:

Conclusión

Aunque siempre digo que no debemos influir sobre el comportamiento normal de SQL Server en estos casos siempre hago una excepción. Nosotros conocemos nuestros datos (o deberíamos) y cuando el parameter sniffing no termine de adaptarse a nuestras necesidades no debemos tener miedo de actuar. Usa todas las herramientas que SQL pone a nuestra disposición y anticipate a las llamadas de usuarios descontentos, Query Store tiene una vista de consultas recursivas que nos mostrará estos casos de una manera muy cómoda. Añade tus sugerencias de consulta o procedimientos y no dejes que nada frene tus consultas.

Espero que este artículo te haya sido útil y que te ayude a optimizar el rendimiento de tus consultas en SQL Server. Si tenéis alguna duda o sugerencia, podéis dejarla en Twitter, por mail o dejarnos un mensaje en los comentarios. Y recuerda que también tenemos un grupo de LinkedIn y un canal de YouTube a los que te puede unir. ¡Hasta la próxima!

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

Parameter Sniffing, ¿aliado o enemigo del rendimiento?

Vamos a pasar el mal trago de ayer con los índices de SQL Server que nos perjudicaban el rendimiento y vamos a ver un aspecto que sí podemos controlar nosotros directamente. Mucho hemos hablado de los índices ya en el blog, y también de que SQL Server hace uso de las estadísticas de las tablas para decidir el plan de ejecución más óptimo. Sin embargo no habíamos profundizado en cómo funciona esto y no, no es por arte de magia. SQL Server va a hacer lo que se conoce como parameter sniffing.

El motor de bases de datos de SQL Server utiliza el parameter sniffing para hacerse una idea del volumen de datos de cada una de las tablas que intervienen en nuestras consultas (con los filtros ya aplicados) y así tomar las mejores decisiones. Como habrás adivinado, el parameter sniffing, más allá del tecnicismo (que quedará muy bien si lo soltamos en mitad de una conversación técnica), es una de las claves para el rendimiento de las consultas en SQL Server.

Planes de ejecución de consulta

Lo primero que tenemos que entender es como SQL calcula los planes de ejecución y para ellos, vamos a intentar llevarlo a algo que todos podamos imaginar, así será fácil de entender. Imagina que trabajas de encargado de almacén y tienes que gestionar el trabajo de los mozos del almacén. Te han encargado la tarea de mover todo el stock de unos determinados productos a otro almacén de la compañía. Entre los distintos productos que tienes que mover hay desde tornillos hasta maquinaria industrial. Para poder asignar recursos a las distintas tareas, tendrás que saber cuántos artículos de cada cosa debes mover y cuáles son sus pesos, ¿verdad?. Pues en SQL Server pasa lo mismo, cuando nosotros le pedimos que nos de unos datos, necesita conocer cuántos registros van a ser y cuanto ocupan para poder hacer una asignación correcta de recursos.

Parameter Sniffing en acción

Como podéis imaginar, calcular el plan tiene un coste y es por esto que SQL cachea esos planes para poder reutilizarlos. Esto es realmente útil cuando las consultas se repiten siempre igual pero, ¿qué pasa si cambian? Almacenaremos gran cantidad de planes y muchos serán iguales. Para eso existen los procedimientos almacenados, fragmentos de código que SQL almacena como un objeto, donde las variables están parametrizadas para que nosotros podamos definirlas en cada ejecución. En estas situaciones el plan de ejecución es siempre el mismo porque la consulta es siempre la misma sea cual sea el valor que le pongamos en los filtros. Esto podemos forzarlo para las consultas ad hoc con la opinión parametrización forzada de SQL Server de la que ya hablamos en profundidad aquí

En estas situaciones SQL Server analizará el volumen de datos que coinciden con ese parámetro y lo usará para generar un plan de ejecución que se utilizará en todas las consultas siguientes. A este procedimiento interno de SQL Server se le conoce como Parameter Sniffing y reduce mucho los tiempos de ejecución cuando tenemos una distribución equitativa de los datos. Es decir, los registros pesan más o menos lo mismo sea cual sea el valor. 

Los problemas de Parameter Sniffing

Como hemos visto el parameter sniffing reduce mucha carga de compilación de los planes de ejecución en consultas con una distribución de datos similar pero, ¿Qué pasa si no es así? Volviendo a nuestro ejemplo anterior, ¿asignaremos los mismos recursos para mover un clavo que para mover una máquina de varias toneladas? Obviamente no, y esto es un problema (o lo era). SQL Server asignará los recursos a la consulta en función del plan de ejecución que tiene almacenado y este se habrá calculado en base a los resultados de la primera ejecución de la consulta. Al menos, históricamente siempre ha sido así. En Microsoft conocedores de este problema, implementaron en SQL 2019 una optimización en el procedimiento de parameter sniffing y en los planes de ejecución añadiendo los adaptative joins. 

Parameter Sniffing a partir de SQL 2019

En las últimas versiones de SQL Server (2019 y 2022), lo que se hace es compilar el plan de ejecución de varias ejecuciones de la consulta. Si el resultado de estas primeras compilaciones es siempre el mismo plan, se cacheará ese y el comportamiento será el de siempre, pero, si los planes cambian, se almacenará un plan con un join adaptativo que permitirá aplicar un plan u otro en función de los parámetros de la consulta.

Parameter Sniffing caso práctico

Vamos a ver esto en la práctica que con ejemplos es como mejor se quedan las cosas. Para ello vamos a usar la base de datos de demo AdventureWorks.

Si os fijáis, en esta primera imagen, la consulta es la misma y solo cambia el valor que le pasamos al filtro. Solo con eso, dada la cardinalidad de la consulta, vemos como el motor de base de datos calcula un plan de ejecución distinto para cada una de ellas.

Vamos a probar ahora a crear el siguiente procedimiento almacenado, como veis es la misma consulta de la imagen de antes pero hecha procedimiento almacenado.

Con el procedimiento creado mirad lo que pasa. Calcula el plan de ejecución en base al primero de los parámetros y ese es el plan de ejecución que se queda para siempre.

Conclusión

Hoy hemos podido aproximarnos más a cómo SQL usa las estadísticas de las tablas para calcular los planes de ejecución y cómo se comporta cuando usamos consultas parametrizadas. Hemos entendido las ventajas y los inconvenientes del parameter sniffing y lo hemos podido ver en un ejemplo práctico. Dejamos para mañana ver cómo, nosotros como DBAs, podemos influir sobre ello y sacarle todo el partido.

Espero que este artículo te haya sido útil y que te ayude a optimizar el rendimiento de tus consultas en SQL Server. Si tenéis alguna duda o sugerencia, podéis dejarla en Twitter, por mail o dejarnos un mensaje en los comentarios. Y recuerda que también tenemos un grupo de LinkedIn y un canal de YouTube a los que te puede unir. ¡Hasta la próxima!

Publicado por Roberto Carrancio en Rendimiento, SQL Server, 0 comentarios
Un índice que no se usa perjudica el rendimiento de los select

Un índice que no se usa perjudica el rendimiento de los select

¿Alguna vez os han dicho que un índice que no se usa empeora el rendimiento de una consulta SELECT? Todos hemos oído que los índices penalizan la escritura y eso es cierto como que odio madrugar para trabajar pero, las lecturas no se ven afectadas, ¿verdad? ¿Estáis seguros? Recientemente recibí en mi bandeja de entrada el último boletín de la newsletter de SQLAuthority sobre un extraño comportamiento con los índices en SQL Server y me ha parecido tan interesante que he sentido la necesidad de compartirlo con vosotros. Aunque, como os digo, la idea detrás de este post no es mía y es plenamente de Pinal Dave me voy a tomar la libertad de traducirlo y compartirlo con vosotros.

Introducción

Este email que activó mi sentido arácnido:

Hi there,
Have you ever seen that Index which is not used for the query reduces the performance of the SELECT statement?
If yes, good, you can stop reading this email here.
If no, here is the video you MUST WATCH 
That’s it! Have a good day.
~ Pinal from SQL Authority

Cuando lo he leído no me lo podía creer, ¿cómo un índice que no se usa puede empeorar el rendimiento de una consulta de lectura? Sabemos que los índices empeoran los procesos de escritura pero, es justamente porque se usan y se escribe en ellos además de en la tabla. Pero en las lecturas no, eso no es lo que dicen los libros de SQL. Sin embargo, de Pinal me fio completamente (ha demostrado sobradamente saber mucho de esto) así que he ido al video y en efecto, en él demuestra empíricamente lo que dice en el correo.

Tan atónito estaba al terminar los doce minutos de demo de Pinal que he ido raudo a comprobarlo en mi propio servidor de pruebas. En el video, Pinal usa la base de datos AdventureWorks2014 y en las respuestas a los comentarios dice haberlo probado tanto con modo de compatibilidad 2017 como 2019. En mi laboratorio de pruebas yo tengo un 2022 así que perfecto vamos a ver que pasa.

Consulta sin índice

Ejecutamos la consulta sobre la tabla, sin haber creado ningún índice vemos que hace un escaneo de la PK que supone el 42% de la consulta. En cuanto a lecturas, si miramos los mensajes de las estadísticas de E/S vemos que se está leyendo 1238 páginas de disco de 8 Kb, lo que son aproximadamente 10 Mb de datos. Sin embargo para leer esos 10Mb de datos, necesita una tabla auxiliar de la que lee 368.495 páginas o lo que es lo mismo 2,8 Gb de información.

Creemos un índice

Obviamente este rendimiento no es el esperado, leer casi 3 Gb de información para devolver 10 Mb, no sé a vosotros, pero a mi no me parece correcto. Así que creemos un índice llamado IX_1 tal como aprendimos en este otro post y probemos. Vale, tenemos dos lecturas de la tabla y eso no es lo mejor, pero tampoco es un problema. Mirad las estadísticas, tenemos simplemente 610 páginas leídas o lo que es lo mismo, 5Mb de información. 

Creando otro índice

Un caso de uso normal sería ahora crear otro índice invirtiendo el orden de los campos clave para verificar si el rendimiento mejora o no. Sin embargo, al hacerlo, nos vamos a encontrar con la sorpresa que da título a este post. No solo la consulta sigue usando el primero de los índices sino que han vuelto los Table Spool y aunque las páginas leidas de la tabla han bajado a la mitad que antes, tenemos otra vez esos casi 3 Gb de lecturas de la tabla de trabajo. 

Otras pruebas

No os voy a aburrir con más capturas de pantalla, creo que ya lo habéis pillado. Deciros que lo he probado en todos los niveles de compatibilidad posibles de una base de datos desde SQL 2014 hasta 2022 y el resultado ha sido idéntico. 

También he probado con actualizaciones de las estadísticas de la tabla, borrando la caché de planes de ejecución entre las pruebas, con el hint de index para forzarle el uso del índice en las dos ejecuciones y con un hint de RECOMPILE. Todo con el mismo resultado. Para terminar he cambiado la consulta y he usado un join en vez de la subquery pero nada, en todos los casos aparecían esas lecturas al tener el segundo índice creado aunque en el plan de ejecución no aparezca en uso por ningún lado y al borrarlo volvía a los dos escaneos sin lecturas de tablas auxiliares. 

Os diré más, en este punto con ya el artículo escrito se me ha ocurrido una cosa, he borrado el índice 2, he ejecutado la consulta que se ha ejecutado con el plan correcto, he ido a Query Store y he forzado ese plan, luego he creado el índice y, ¿sabéis que? LO HA VUELTO A HACER MAL. Si amigos, incluso forzando en Query Store el plan correcto, SQL me ha sacado el dedo y ha hecho lo peor para él, como un hijo adolescente que no entiende que miras por su bien.

Conclusiones

¿Y ahora que digo yo? ¿Qué conclusión sacamos de esto? Que lo que pone en los libros no es correcto? Igual es que SQL Server hace cosas sin sentido o que visto esto debería pasarme a Oracle? Lo cierto es que no he conseguido encontrar una explicación a lo que está pasando pero ahí está. En su video, Pinal llega al mismo punto, no entiende lo que pasa y obviamente no tiene sentido. Parece un bug del motor de base de datos sin resolver desde hace un montón de tiempo. Por mi parte seguiré probando esto en cada nueva versión de SQL Server y si veo que se resuelve espero poder avisaros por aquí. De momento, no nos queda otra, revisemos los índices de nuestras bases de datos y borremos los que no estén en uso por si nos están penalizando.

Espero que este artículo te haya sido útil y que te ayude a optimizar el rendimiento de tus consultas en SQL Server. Si tenéis alguna duda o sugerencia, podéis dejarla en Twitter, por mail o dejarnos un mensaje en los comentarios. Y recuerda que también tenemos un grupo de LinkedIn y un canal de YouTube a los que te puede unir. ¡Hasta la próxima!

PD.: Si alguno queréis ir a la fuente original os dejo el vídeo por aquí.

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