Roberto Carrancio

Mi nombre es Roberto Carrancio y soy un DBA de SQL server con más de 10 años de experiencia en el sector. Soy el creador del blog soydba.es donde intento publicar varios artículos a la semana (de lunes a viernes que los fines de semana me gusta estar con mi gente y disfrutar de mi moto) Espero que disfrutes leyendo este blog tanto como yo disfruto escribiendo y que te sea de utilidad. Si tienes alguna sugerencia, pregunta o comentario, puedes dejarlo al final de cada entrada o enviarme un correo electrónico. Estaré encantado de leerte y responderte. ¡Gracias por tu visita! Mi principal interés es compartir mi conocimiento sobre bases de datos con todo el que quiera aprenderlo. Me parece un mundo tan apasionante como desconocido. Fuera de lo profesional me encanta la cocina, la moto y disfrutar de tomar una cervecita con amigos.
Mi nombre es Roberto Carrancio y soy un DBA de SQL server con más de 10 años de experiencia en el sector. Soy el creador del blog soydba.es donde intento publicar varios artículos a la semana (de lunes a viernes que los fines de semana me gusta estar con mi gente y disfrutar de mi moto) Espero que disfrutes leyendo este blog tanto como yo disfruto escribiendo y que te sea de utilidad. Si tienes alguna sugerencia, pregunta o comentario, puedes dejarlo al final de cada entrada o enviarme un correo electrónico. Estaré encantado de leerte y responderte. ¡Gracias por tu visita! Mi principal interés es compartir mi conocimiento sobre bases de datos con todo el que quiera aprenderlo. Me parece un mundo tan apasionante como desconocido. Fuera de lo profesional me encanta la cocina, la moto y disfrutar de tomar una cervecita con amigos.

Always On Availability Groups (HA Parte 2)

Como adelantamos ayer en la introducción sobre las distintas soluciones de alta disponibilidad que ofrece SQL Server vamos a profundizar una a una en cada una de ellas. Hoy en concreto vamos a hablar de la joya de SQL Server en este sentido, los grupos de disponibilidad Always On. Los Always On de SQL Server son una solución de alta disponibilidad y recuperación ante desastres que permite tener varias réplicas de una base de datos en diferentes servidores o ubicaciones. En este artículo, vamos a explicar cómo funcionan, qué ventajas ofrecen y cómo configurarlos paso a paso.

¿Qué son los grupos de disponibilidad Always On?

Los grupos de disponibilidad Always On son una característica introducida en SQL Server 2012 que nos permite tener hasta ocho réplicas secundarias de una base de datos primaria. Las réplicas secundarias se sincronizan automáticamente con la primaria de manera síncrona o asíncrona. Cada réplica secundaria puede tener un rol diferente, según el nivel de compromiso con la primaria y el tipo de operaciones que se permiten realizar sobre ella.

Los Always On permiten que las réplicas secundarias pueden estar en el mismo servidor o en servidores distintos, e incluso en diferentes regiones geográficas o la nube. Esto nos ofrece una gran flexibilidad y escalabilidad para adaptarlos a las necesidades de cada escenario.

Nivel de compromiso de las réplicas secundarias

Como hemos dicho, la replicación puede ser síncrona o asíncrona, esto es un factor clave a la hora de diseñar nuestra solución de alta disponibilidad y afectará a todo lo demás.

Replicación síncrona

Las réplicas secundarias se comprometen a aplicar los cambios recibidos de la primaria antes de confirmar la transacción al cliente. Esto quiere decir que sin tener confirmación de todas las réplicas síncronas la transacción no se va a confirmar. Esto nos garantiza que las réplicas están siempre en el mismo estado, evitando la pérdida de datos, pero afectando al rendimiento de las escrituras. Las réplicas síncronas pueden tomar el rol de primaria en caso de fallo, mediante un proceso de conmutación por error automático o manual. Usaremos este tipo de réplicas como solución de alta disponibilidad siempre que la latencia de red no sea un problema. En este sentido, es recomendable usar una red dedicada para la replicación del Always On independiente a la red de servicio a los usuarios.

Replicación asíncrona

Las réplicas no se comprometen a aplicar los cambios recibidos de la primaria inmediatamente, sino que lo hacen cuando les sea posible. Esto mejora el rendimiento de las operaciones de escritura, pero puede provocar que la secundaria tenga un cierto retraso respecto a la primaria. Las réplicas asíncronas pueden tener pérdidas de datos por lo que requieren una intervención manual para forzar la conmutación por error.

Acceso a los grupos de disponibilidad Always On

Para facilitar el acceso a las bases de datos del Always On, se utiliza el listener, que es un nombre virtual que representa al grupo de disponibilidad y que se resuelve en la dirección IP de la réplica primaria o de una réplica secundaria legible, según el criterio de enrutamiento que se defina. El listener permite a las aplicaciones conectarse al grupo de disponibilidad sin tener que conocer el nombre o la dirección IP de cada réplica. Cuando conectamos al listener este nos redirigirá siempre a la réplica primaria a no ser que le especifiquemos lo contrario mediante el parámetro ApplicationIntent=ReadOnly que nos llevará a una réplica secundaria de solo lectura.

Para configurar el listener, se debe especificar un nombre, un puerto y una dirección IP para cada subred en la que se encuentren las réplicas. Además, se debe crear un registro DNS con el nombre del listener y las direcciones IP asignadas. 

Nivel de acceso a las réplicas secundarias

Hemos estado comentando que podemos acceder a las réplicas secundarias en modo de lectura. Realmente, pueden tener diferentes modos de acceso, según el tipo de consultas que se puedan ejecutar sobre ellas, vamos a verlo:

Modo solo lectura

Permite ejecutar consultas de solo lectura sobre la réplica secundaria, lo que puede servir para balancear la carga de trabajo o para realizar operaciones de mantenimiento o copia de seguridad sin afectar a la primaria. Para habilitar este modo, es necesario que la réplica secundaria esté sincronizada con la primaria y que tenga habilitada la opción READ_ONLY_ROUTING_URL, que indica la dirección a la que deben dirigirse las conexiones de solo lectura.

Modo solo intención de lectura

Permite ejecutar consultas de solo lectura sobre la réplica secundaria, pero solo si la conexión especifica explícitamente esa intención mediante el parámetro ApplicationIntent=ReadOnly. Esto puede servir para separar las conexiones que requieren acceso a la primaria de las que pueden usar una secundaria, según el criterio de la aplicación cliente. Para habilitar este modo, se requieren las mismas condiciones que para el modo solo lectura.

Modo sin acceso

No permite ejecutar ninguna consulta sobre la réplica secundaria, solo se usa para mantener una copia sincronizada con la primaria. Este modo se usa cuando no se desea dar acceso a los datos de la secundaria o cuando la réplica está en proceso de sincronización o restauración. Si contamos con una licencia de SQL Server con Software Assurance es probable que optemos por este modo de réplica secundaria ya que no requiere de licencia adicional para la instancia secundaria.

¿Qué ventajas ofrecen los grupos de disponibilidad Always On?

Los grupos de disponibilidad Always On ofrecen varias ventajas como solución de alta disponibilidad y recuperación ante desastres:

– Permiten tener varias copias de una base de datos en diferentes servidores o ubicaciones, lo que aumenta la protección ante fallos o desastres.

– Pueden conmutar por error entre réplicas de forma automática o manual, lo que reduce el tiempo de inactividad y facilita la administración.

– Nos ayudan a balancear la carga de trabajo de nuestro servidor pudiendo delegar en las réplicas secundarias las consultas de solo lectura y las copias de seguridad.Para esto último,se debe configurar la opción «Backup priority» en las propiedades del grupo de disponibilidad.

– Permiten acceder a los datos de las réplicas secundarias para consultas de solo lectura o para operaciones de mantenimiento o copia de seguridad, lo que mejora el rendimiento y la escalabilidad.

– Se integran con otras características de SQL Server, como el agrupamiento en clústeres Windows Server Failover Cluster (WSFC), el servicio Broker para controlar el flujo

de mensajes entre las réplicas o el Listener para facilitar el acceso a las bases

de datos mediante un nombre virtual.

¿Qué requisitos se necesitan para usar los grupos de disponibilidad Always On?

Para usar los grupos de disponibilidad Always On se necesitan cumplir los siguientes requisitos:

– Tener instalada la edición Enterprise de SQL Server 2012 o superior, ya que la edición Standard solo permite tener una réplica secundaria y no admite el modo solo lectura ni el enrutamiento de lectura. La edición Developer también admite los grupos de disponibilidad Always On, pero solo para fines de desarrollo y pruebas.

– Tener configurado un clúster WSFC con al menos dos nodos, que serán los servidores donde se alojarán las réplicas primaria y secundaria. El clúster WSFC se encarga de monitorizar el estado de las réplicas y de realizar la conmutación por error si es necesario.

– Tener las bases de datos que se quieren proteger en modo de recuperación completa, lo que implica hacer copias de seguridad periódicas del log de transacciones para evitar que crezca demasiado.

¿Cómo se configuran los grupos de disponibilidad Always On?

Para configurar los grupos de disponibilidad Always On se deben seguir los siguientes pasos:

– Crear un grupo de disponibilidad en el servidor que aloja la base de datos primaria, especificando el nombre del grupo, las bases de datos que se quieren proteger y las opciones de configuración, como el modo de conmutación por error o el modo de acceso a las réplicas secundarias.

– Añadir una o más réplicas secundarias al grupo de disponibilidad, especificando el servidor donde se alojan, el modo de compromiso y el modo de acceso. También se debe indicar si la réplica secundaria será una copia de seguridad preferente o si tendrá habilitado el enrutamiento de lectura.

– Inicializar las réplicas secundarias mediante una copia de seguridad y restauración de las bases de datos primarias o mediante una sincronización automática si se dispone de una conexión compartida entre los servidores.

– Verificar el estado y el funcionamiento del grupo de disponibilidad, comprobando que las réplicas están sincronizadas, que se pueden realizar consultas sobre ellas y que se puede conmutar por error entre ellas.

Conclusión

Los grupos de disponibilidad Always On son una solución avanzada y flexible para garantizar la alta disponibilidad y la recuperación ante desastres de las bases de datos SQL Server. Permiten tener varias réplicas sincronizadas de una base de datos primaria, que pueden asumir el rol de primaria en caso de fallo o servir para consultas de solo lectura o para operaciones de mantenimiento o copia de seguridad. Para usar esta característica se requiere tener la edición Enterprise de SQL Server 2012 o superior y configurar un clúster WSFC. En este artículo hemos explicado cómo funcionan los grupos de disponibilidad Always On, qué ventajas ofrecen y cómo configurarlos paso a paso. Si os ha quedado alguna duda o comentario ya sabeis que podeis ponerlo aquí en los comentarios, mandarme un mail o en twitter.

Publicado por Roberto Carrancio en Alta Disponibilidad, SQL Server, 14 comentarios

Alta Disponibilidad en SQL Server Introducción (HA Parte 1)

Hoy iniciamos una nueva serie en la que vamos a hablar sobre las distintas soluciones de alta disponibilidad que existen para SQL Server. Antes de nada vamos a aclarar los conceptos básicos sobre los que profundizaremos tanto hoy como estos próximos días. A continuación, vamos a resumir brevemente las distintas soluciones de SQL Server que tenemos a nuestro alcance. Solo un breve resumen ya en los próximos artículos que las veremos más en profundidad.

¿Qué es la Alta Disponibilidad?

La alta disponibilidad se refiere a la capacidad de un sistema de seguir funcionando sin interrupciones ante posibles fallos o desastres, ya sean de hardware, software o de infraestructura. 

¿Por qué es importante? 

La alta disponibilidad es importante porque nos permite garantizar la continuidad del negocio, la satisfacción de los clientes y el cumplimiento de los acuerdos de nivel de servicio (SLA).

Aspectos clave para implementar una solución de Alta Disponibilidad

Para evaluar la adecuación de una solución de alta disponibilidad, es necesario tener en cuenta dos conceptos clave: el punto de recuperación objetivo (RPO) y el tiempo de recuperación objetivo (RTO). El RPO indica la cantidad máxima de datos que se pueden perder en caso de un fallo, mientras que el RTO indica el tiempo máximo que se puede tardar en restaurar el servicio. Estos valores dependen del nivel de criticidad del sistema y del presupuesto disponible, y pueden variar desde unos pocos segundos hasta varias horas o días.

Distintas soluciones de Alta Disponibilidad

SQL Server ofrece varias opciones para implementar la alta disponibilidad, dependiendo de las necesidades y los recursos de cada organización. Algunas de las más conocidas son:

Grupos de disponibilidad Always On

Esta es una solución replica datos de forma síncrona o asíncrona entre varias réplicas secundarias con una conmutación por error automática o manual. Los grupos de disponibilidad Always On tienen una réplica primaria que recibe las transacciones y las envía a las réplicas secundarias, que pueden estar en la misma red local o en ubicaciones remotas. Además, las réplicas secundarias pueden usarse para realizar consultas de solo lectura, copias de seguridad o restauraciones, lo que mejora el rendimiento y la escalabilidad de nuestro sistema.

Always On ofrece un RPO y un RTO muy bajos, ya que los datos se sincronizan casi en tiempo real y la conmutación por error se realiza en cuestión de segundos (incluso milisegundos). Los Always On requieren que las instancias de SQL Server pertenezcan a un clúster de conmutación por error de Windows Server (WSFC) para alta disponibilidad y recuperación ante desastres.

Instancia de clúster de conmutación por error

Consiste en tener varios nodos que comparten un almacenamiento común y que pueden asumir el rol de servidor activo en caso de que el nodo principal falle. Los clústeres de conmutación de instancia requieren una configuración especial del hardware, el software y la red, así como una coordinación entre los nodos mediante un testigo (witness). Los clústeres de conmutación de instancia garantizan la disponibilidad del servicio, pero no protegen contra la pérdida o corrupción de los datos al compartir el almacenamiento de los datos. Esta solución tiene un RPO y un RTO moderados, ya que dependen del tiempo que se tarde en detectar el fallo y en activar el nodo secundario. Los clústeres de conmutación de instancia requieren que las instancias de SQL Server estén instaladas en servidores miembros de un clúster WSFC

Database mirroring (Espejo de bases de datos)) 

Esta solución consiste en tener dos instancias de SQL Server que mantienen una copia idéntica de una base de datos mediante el envío del log de transacciones. El database mirroring puede operar en modo síncrono o asíncrono, y puede tener una instancia testigo que supervise el estado de las dos instancias y realice la conmutación por error automáticamente en caso necesario. Proporciona protección contra la pérdida o corrupción de los datos, pero solo se aplica a una base de datos a la vez. Tiene otras limitaciones como que no admite el cifrado transparente de datos (TDE) o los cambios de esquema en línea. Esta solución tiene un RPO y un RTO variables, dependiendo del modo elegido y del tamaño del log.

Log shipping (Envío de Log)

Tendremos una instancia primaria que realiza copias de seguridad periódicas del log de transacciones y las enviará a una o más instancias secundarias que las restauran. El log shipping permite tener varias copias actualizadas (o casi) de una base de datos en diferentes ubicaciones, lo que facilita la recuperación ante desastres. Sin embargo, no ofrece una conmutación por error automática ni una sincronización en tiempo real, por lo que puede haber una pérdida o inconsistencia de los datos. Esta solución tiene un RPO y un RTO altos, ya que dependen de la frecuencia y la duración de las copias de seguridad y las restauraciones.

Otras soluciones de alta disponibilidad

Estas son algunas de las soluciones más populares para lograr la alta disponibilidad en SQL Server, pero no son las únicas. También existen otras opciones como la replicación, el almacenamiento distribuido o los servicios en la nube. Lo importante es evaluar las ventajas y desventajas de cada una, así como los requisitos y objetivos del negocio, para elegir la más adecuada.

Conclusión

Como hemos podido ver SQL Server ofrece diversas soluciones de alta disponibilidad que se adaptan a diferentes escenarios y necesidades. Algunas de estas soluciones requieren un clúster WSFC, mientras que otras no. Es importante conocer las características, ventajas y limitaciones de cada opción, así como los conceptos de RPO y RTO, para tomar una decisión informada y optimizar el rendimiento y la seguridad de los datos.

Espero que os haya gustado este artículo y que os sirva para conocer mejor las opciones de alta disponibilidad que ofrece SQL Server. Como siempre, cualquier duda o comentario, podéis dejarla aquí abajo, por mail o en twitter

Publicado por Roberto Carrancio en Alta Disponibilidad, SQL Server, 7 comentarios
Lotería de Navidad en SQL Server

Lotería de Navidad en SQL Server

Hoy es 22 de Diciembre, día en que se celebra el sorteo de la lotería de Navidad en España. A mi personalmente no me gustan los juegos de azar y menos con dinero de por medio, me parece que la ludopatía es una enfermedad que se debe combatir y no lucrarse con ella como administración. Sin embargo, me parece una buena ocasión para aprender a generar datos aleatorios en SQL Server. Vamos a crear nuestro propio sorteo de navidad. Vais a ver que hay formas mucho más fáciles de llegar al objetivo final, sin embargo vamos a tratar de aprender el mayor número posible de cosas durante el ejercicio y por tanto a complicarlo.

Nuestro sorteo de lotería

Para nuestro sorteo, igual que en la lotería de navidad, tendremos 100.000 números distintos con los que jugar, es decir números entre 0 y 99.999. También tendremos 5 premios. Nuestro objetivo será crear una consulta SQL Server que devuelva 5 números aleatorios y los asigne a un número de premio entre el 1 y 5. Para terminar creamos un comprobador de premios que nos diga cuánto dinero nos ha tocado. 

Crear nuestro sorteo de Navidad

Modelo de datos del sorteo

Siempre que iniciamos un proyecto nuevo en SQL tenemos que definir el que va a ser el modelo de datos que vamos a usar. Esto implica las tablas y los tipos de datos que van a admitir. Tenemos que pensarlo muy bien ya que cambiarlo luego será costoso y debe estar preparado para dimensionarse y añadirle nuevas funcionalidades en un futuro. Nuestro ejemplo es sencillo y como es solo un ejercicio no tenemos que pensar en tantas cosas. Vamos a crear una tabla con todos los posibles números, una tabla con los premios y el importe del premio y otra donde vamos a almacenar los resultados.

Tabla números del sorteo:

Esta es una tabla sencilla, simplemente vamos a necesitar una columna para almacenar todos los posibles números. Si recordáis el primer artículo de este blog hablamos sobre los tipos de datos numéricos y vimos cual era el mejor para cada situación, en nuestro caso el que mejor se adapta es el int. Será un campo que no admite nulos y como tampoco va a tener duplicados será nuestra PK.

Tabla premios

En esta tabla vamos a almacenar dos consultas, el premio y el importe del mismo. El premio será un número del 1 al 5 por lo que nos vale con un campo tinyint y el importe lo vamos a crear como numérico. Ninguno de los campos admitirá nulos y el número de premio será nuestra PK

Tabla resultados de la lotería

Aquí vamos a almacenar los resultados del sorteo de la lotería. Vamos a necesitar una columna con el número del premio y otra con el número premiado. Las columnas tendrán el mismo tipo de datos que en las otras tablas, no admitirán nulos, no podrán contener ningún valor que no exista en las otras tablas ni valores duplicados. Para ello además de una PK compuesta por ambos campos vamos a crear una FK hacia las otras tablas.

Cargar datos en las tablas de la lotería

Vamos a cargar datos en nuestras tablas de loterías, para los números vamos a usar un bucle. Declararemos una variable i con un valor igual a 0 y mientras cumpla la condición de ser menor que 100.000 insertaremos su valor en la tabla y luego le sumaremos 1. Para los premios definiremos directamente los valores a insertar

Sorteo de la lotería de Navidad

Llegó el momento que toda España está esperando, ya tenemos cargados los dos bombos, digo las dos tablas y es la hora de iniciar el sorteo. Vamos a crear una consulta que seleccione uno de los números y uno de los premios al azar, el único requisito es que no hayan salido antes. Esa combinación ganadora la vamos a insertar en nuestra tabla de resultados. Ejecutaremos la consulta en bucle hasta que deje de devolver valores porque no queden premios sin un número asignado. Esta es mi solución propuesta:

En mi caso este ha sido el resultado:

Comprobar décimos lotería de navidad

Ya tenemos a los ganadores de nuestra lotería de navidad, ahora es el momento de facilitar a los usuarios una herramienta para que puedan comprobar si su décimo ha sido o no premiado. Vamos a crear un procedimiento almacenado que nos diga si nuestro número ha sido premiado o no. Si ha sido premiado nos dirá cuánto dinero nos ha tocado.

Ahora podremos ejecutar nuestro procedimiento almacenado pasándole el número que estamos jugando como parámetro y nos dirá si hemos sido o no premiados.

Conclusión

Con el juego de hoy hemos tenido la oportunidad de ver variedad de sintaxis de SQL Server. Para crear nuestro sorteo hemos creado tablas con Primary y Foreign Keys, hemos visto como crear consultas que se ejecutan en bucle y CTEs. Para el comprobador no nos hemos quedado cortos, hemos creado un procedimiento almacenado con validaciones, conversiones de tipos de datos y textos concatenados.

Como os he dicho al principio hay maneras más sencillas de conseguir el mismo resultado, esta ha sido mi propuesta para enseñaros todo lo posible en un espacio limitado. Ahora os reto a que juguéis vosotros también, pero no a la lotería sino a crearla en vuestras bases de datos. Hacedlo a vuestra manera y compartidme vuestras soluciones, seguro que entre todos encontramos soluciones ingeniosas. Os leo en los comentarios, mucha suerte !!

Publicado por Roberto Carrancio en SQL Server, 0 comentarios

Uso, llenado y mantenimiento de índices (Índices parte 7)

A lo largo de las pasadas 6 entradas hemos repasado todos los distintos tipos de índices en SQL Server. Sin embargo, hay aspectos que, aunque comentamos por encima en la introducción, no habíamos vuelto a profundizar y son los que vamos a ver. Durante estas líneas vamos a hablar sobre cuándo y cómo SQL Server hace uso de los índices. Además, veremos cómo se van llenando las páginas y cómo podemos influir nosotros en ello, un aspecto que afectará a la fragmentación. Por último aprenderemos cómo crear un plan de mantenimiento que solucione este problema.

Uso de índices y estadísticas

Sea cual sea el índice que creemos, SQL Server generará una estadística sobre él. De esta manera, podrá decidir si es recomendable buscar los registros a través de los niveles del  árbol B, leer directamente el nivel de hoja en busca de los registros o recorrer enteramente la tabla y no usar el índice. 

Cuando ejecutamos una consulta, SQL Server calculará distintos planes de ejecución con todas las opciones de recuperar los datos. En una tabla pequeña de menos de 10.000 páginas es fácil, se va a leer la tabla y no se usarán los índices nonclustered. Cuando tiene más, se usarán las estadísticas de los índices nonclustered para calcular el porcentaje de registros que se van a recuperar. En función de esos datos asignará un coste a cada uno de los planes de ejecución. Con todos los costes calculados se elegirá la mejor opción.

Llenado de índices y tablas

Hemos comentado en varias ocasiones que los datos en SQL se escriben en páginas. Vimos que en las tablas HEAP que los datos se escriben en el primer hueco libre disponible y, a la hora de editar, si el nuevo valor no cabe se mueve al final. Esto generaba punteros de reenvío y fragmentación.

En el caso de los índices clustered y nonclustered los datos se escriben en páginas igualmente. SQL Server intentará escribir el datos en su sitio pero, solo lo hará si hay sitio libre. Si no lo hay, lo escribirá en el espacio libre más próximo. 

Fill Factor

Dado este comportamiento, para reducir al máximo la fragmentación y aprovechar el espacio de manera óptima podemos definir en los índices un nivel de llenado o Fill Factor. Este Fill Factor es un porcentaje que indicará al SQL cuánto espacio de las páginas de los índices se va a llenar de datos (no aplica para tablas HEAP). Por tanto, podremos controlar cuánto espacio se va a dejar libre al final de las páginas.
Podremos definir un nivel genérico en las propiedades de la instancia además de uno particular para cada índice si no queremos que use el genérico. Si no definimos otra cosa el fill factor será del 100%, es decir SQL tratará de llenar completamente las páginas. Esto puede ser una buena idea para índices en campos incrementales que nunca se editan. Sin embargo, si este no es el caso, llenar completamente las páginas nos generará tener que mover los datos o no escribirlos donde toca. En resumen, un mayor consumo de E/S y por tanto peor rendimiento.

Mantenimiento de índices

Acabamos de ver que muy probablemente nuestros índices se van a fragmentar con el uso, así que, como DBAs, es imprescindible que tengamos una buena política de mantenimiento que garantice que se encuentren en óptimas condiciones. Para ello tenemos varias alternativas, reorganizarlos o reconstruirlos. El método elegido dependerá en gran medida de la fragmentación que tenga el índice al momento de optimizarlo. Como norma general, reorganizaremos los índices con menos de un 30% de fragmentación y reconstruiremos los más fragmentados.
Además, tendremos que implementar también un mantenimiento de las estadísticas, como hemos visto son claves para que el motor de bases de datos calcule los costes de los planes de ejecución y decida por cuál de ellos decantarse. La reconstrucción de índices conlleva el mantenimiento de estadísticas, pero la reorganización no, por lo que tendremos que hacerlo por separado. Como os comenté en el artículo de las tareas diarias de un DBA, yo me decanto por la solución de olla hallengren

Aunque un mantenimiento de las estadísticas es clave para el rendimiento de nuestra base de datos no tenemos que caer en el error de ejecutarlo con demasiada frecuencia.Cada vez que se actualizan estadísticas, todos los planes de ejecución que tenemos en la caché de SQL Server y que usan esas tablas se van a desechar. Esto provocará que la próxima ejecución de la consulta necesite recompilar el plan, calcular todas las opciones y elegir el de menos coste. Para esto, la solución de ola, tiene un parámetro para solo actualizar las estadísticas que hayan sufrido modificaciones desde la última actualización, lo que liberará a SQL Server de carga de trabajo innecesaria. 

Conclusión

Dado que con este artículo cerramos la serie de índices, permitidme que por una vez me extienda un poco más en la conclusión y recapitulemos todo lo visto. Primero de todo quiero daros las gracias a vosotros, habéis llevado las páginas de esta serie a las primeras posiciones de las estadísticas de visitas del blog en muy pocos días. 

Ahora ya sí, entremos en materia. Empezamos esta serie con una introducción donde vimos las estructura de las tablas en SQL Server y descubrimos la importancia de los índices.

Después analizamos los distintos tipos de índices que podemos usar en SQL Server, desde la ausencia de ellos en una tabla HEAP, índices clustered, nonclustered, columnares y, hasta los índices especiales (únicos, filtrados, espaciales, XML, hash y de texto completo). De todos ellos vimos cómo funcionan, para qué se usan y cuándo son recomendables.Todo este conocimiento adquirido durante los últimos días nos ha traído hasta esta última entrada donde hemos entendido mejor la fragmentación de los índices y cómo combatirla. Además hemos podido comprender la importancia de las estadísticas y su papel clave en el rendimiento de nuestro SQL Server. 

Seguro que los más expertos echaréis en falta algún que otro aspecto relacionado con los índices o que entremos más en detalle sobre alguno de los temas tratados, os prometo que habrá más artículos sobre índices en un futuro aunque sea ya fuera de esta serie. 
Como siempre, tenéis a vuestra disposición la sección de comentarios, mi mail y nuestra cuenta de twitter para cualquier aportación o sugerencia. 
¡Espero que os haya gustado esta serie y hayáis aprendido cosas nuevas!

Contenido de la serie

Introducción a los índices en SQL Server (Índices parte 1)

Estructura física de las tablas y HEAP (Índices parte 2)

Índices Clustered y Primary Keys (Índices parte 3)

Índices Nonclustered (Índices parte 4)

Índices Columnares (Índices parte 5)

Índices especiales (Índices parte 6)

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

Índices especiales (Índices parte 6)

Sexta entrega de esta amplia serie sobre índices donde hemos podido aprender en profundidad todo sobre los principales índices de SQL Server. Antes de entrar en detalle sobre el uso y mantenimiento de los mismos vamos a terminar de repasar rápidamente los tipos de índices especiales.Estos índices especiales son, en su mayoría, específicos para casos concretos de uso y, si bien su uso está mucho menos extendido, como DBAs tenemos que conocer. 

Índices especiales para funcionalidades comunes en SQL Server

Este tipo de índices están pensado para ampliar la funcionalidad de los índices existentes y que hemos repasado en anteriores entradas de esta serie. Hablamos de los índices únicos y los índices filtrados y podríamos decir que existen para complementar al resto de índices.

Índices únicos

La unicidad en una columna es una restricción que se utiliza para mantener la integridad de los datos. Como ya vimos cuando hablamos de las PK, una restricción es una medida lógica que necesita reforzarse con un índice físico. Siempre que queramos crear una restricción de unicidad se creará por defecto un índice nonclustered sobre esa(s) columna(s). También podremos añadir la cláusula UNIQUE al crear un índice clustered o nonclustered.

A la hora de borrarlos, tenemos que tener en cuenta que si la restricción de unicidad se ha creado como restricción (constraint). Si el índice se ha creado automáticamente para reforzar una constraint no podremos usar la sintaxis DROP INDEX y deberemos usar DROP CONSTRAINT. Si hemos creado un índice con la cláusula UNIQUE sí que deberemos usar DROP INDEX.

Índices Filtrados

En ocasiones creamos un índice para mejorar el rendimiento de unas consultas que siempre filtran por los mismos valores de una columna. En estos casos podremos agregar un predicado where a nuestros índices nonclustered (columnstore o árbol B). Esto reducirá el espacio que ocupa nuestro índice y mejorará su rendimiento. 

Tenemos que tener en cuenta que cuanto más lógica añadamos a nuestros índices más le costará a SQL Server mantenerlos. Si el conjunto de resultados resultantes de los filtros del índice, es similar al total de la tabla seguramente no será rentable mantenerlo y deberemos crear un índice de tabla-completa.

Índices especiales para columnas especiales en SQL Server

A lo largo de las distintas versiones de SQL se ha ido añadiendo soporte para información especial. Estos índices que vamos a ver a continuación están pensados para dar soporte a este tipo de información especial.

Índices espaciales

A partir de SQL Server 2008 se introdujeron las columnas GEOGRAPHY y GEOMETRY, para guardar información de coordenadas o geométrica de puntos, líneas y polígonos respectivamente. Estos tipos de datos se conocen como datos espaciales y para ellos se crearon estos tipos de índices. 

Estos índices solo se pueden crear en tablas que tengan PK y en columnas espaciales. 

Índices XML

Como su propio nombre indica los índices XML son índices especiales para columnas de tipo XML en tablas que tengan PK. A poco que conozcáis el estándar XML entenderéis que estas columnas normalmente almacenan grandes cantidades de información de distintos tipos agrupadas en categorías. 

Existen dos tipos de índices XML, los primarios y los secundarios. Crearemos un índice XML primario para indexar las columnas XML. Después de crear el índice primario podremos crear índices XML secundarios para etiquetas concretas dentro de esa columna.

Índices especiales para características especiales de SQL Server

Igual que nos ha pasado en el apartado anterior, SQL ha ido implementando nuevas características para las que ha implementado los índices concretos que vamos a ver ahora. 

Índices hash

Son un tipo de índice especial para tablas optimizadas para memoria. Todas las tablas optimizadas para memoria requieren de un índice de este tipo o un índice nonclustered optimizado para memoria. Sin entrar mucho más en detalle, tenemos que saber que son un tipo de índice que almacena hash de la información ocupando una cantidad de memoria fija.

Índices de texto completo

Este tipo de índices son creados, usados y mantenidos por el motor de SQL Full-text. Permiten a las consultas Full-Text localizar cadenas de texto, para ello dividen las columnas en tokens que luego almacenan en el índice. 

Conclusión

Concluimos con esta sexta entrega el repaso a los distintos tipos de índices que nos podemos encontrar en SQL Server. Hoy hemos aprendido cuáles son los índices especiales que se adaptarán a casuísticas concretas de nuestras instalaciones. Seguid atentos al blog que a partir de mañana empezaremos a ver aspectos más prácticos sobre este mismo tema. Y ya para cerrar lo que os digo siempre, animaos a dejarme vuestras dudas y comentarios aquí debajo o en twitter o por mail.

Contenido de la serie

Introducción a los índices en SQL Server (Índices parte 1)

Estructura física de las tablas y HEAP (Índices parte 2)

Índices Clustered y Primary Keys (Índices parte 3)

Índices Nonclustered (Índices parte 4)

Índices Columnares (Índices parte 5)

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

Índices Columnares (Índices parte 5)

Quinta entrega de nuestra serie de índices y aún nos queda mucho que ordenar. Después de haber visto los tipos de índices más comunes, hoy nos vamos a adentrar en los índices columnares, un tipo de índice no tan conocido pero muy usado en entornos OLAP y datawarehouse. Esto no es casualidad, veremos que, por sus características, son ideales para almacenar la información de las tablas de hechos en entornos donde se ejecutan gran cantidad de consultas complejas. 

Estructura de los índices columnares

Como hemos estado viendo hasta ahora los datos en SQL se almacenan en páginas de 8Kb donde vamos a guardar la información fila a fila de nuestra tabla. Cada página contiene N filas completas, es decir todas sus columnas (excepto las grandes que se almacenan en páginas LOB o ROW_OVERFLOW). Con los índices columnares vamos a dejar este paradigma y vamos a ver que, gracias a la tecnología de compresión VertiPaq, la información se almacena por columnas y no por filas. Tampoco vamos a hablar de páginas sino de segmentos. Una columna tendrá uno o más segmentos de datos. Aunque cambiemos el término tenéis que saber que un segmento es una página que almacena datos de una única columna.
Esto nos va a permitir reducir la E/S en gran medida al leer solo algunas columnas de la tabla ya que no vamos a tener que recuperar las filas completas de datos para luego mostrar unas cuantas columnas. Otra de las ventajas que tiene es que permite comprimir los datos. Normalmente los datos de una columna suelen repetirse y los índices columnares se aprovechan de eso escribiendo el dato solo una vez y añadiendo punteros a ese valor el resto de las veces. Esto se traduce en unas 10 veces menos consumo de disco y unas 10 veces mejor rendimiento en consultas pesadas.

Tipos de índices columnares

Al igual que en los índices de árbol B vamos a tener índices columnares clustered y nonclustered. Cada uno de ellos será ideal para un escenario concreto como vamos a ver a continuación. 

Índice columnar clustered

Al igual que con los índices de almacenamiento de filas (o de árbol B) este índice columnar clustered convierte toda nuestra tabla a almacenamiento de columnas. Sin embargo, no todos nuestros datos se almacenan en formato columnar, hasta que no tengamos aproximadamente un millón de filas los datos se almacenarán en un grupo de filas delta. 

Los grupos de filas delta (almacén delta) son estructuras de árbol B especialmente diseñadas para trabajar con almacén de columnas. Cuando un grupo de filas delta llega a 1.048.576 filas pasa de estado OPEN a CLOSED. En ese momento, un proceso en segundo plano llamado motor de tupla comprime el contenido y lo copia al almacén columnar. El grupo de filas en el almacén columnar pasa a estado COMPRESSED y el grupo del almacén delta se marca para borrar, estado TOMBSTONE (muy poético todo).

Hay una excepción a todo esto que hemos visto y son las cargas masivas o bulk insert. Cuando se produce una carga masiva sobre una tabla con un índice columnar clustered las filas van directamente al almacén de columnas. Se van guardando en grupos CLOSED de un millón de filas. Al finalizar, si el último grupo de filas tiene menos del mínimo de filas permitido (102.400) el grupo se moverá a un almacén delta.
Si la carga masiva directamente es inferior a ese valor mínimo se cargará directamente en un almacén delta. 

Índice columnar nonclustered

No nos vamos a extender mucho, un índice columnar nonclustered funciona igual que un índice columnar clustered. La diferencia es que se almacena separado de la tabla y puede contener desde solo una columna hasta todas las de la tabla. 

Podemos crear un índice columnar nonclustered sobre tablas de árbol B (almacenamiento clásico de filas) lo que nos permite aprovecharnos de las ventajas de estos índices sin sus inconvenientes.

Cuándo elegir un índice columnar

Acabo de deciros que los índices columnares tienen inconvenientes, pero ¿cuáles son? Hasta ahora hemos visto que un índice columnar reduce el consumo de disco y mejora el rendimiento en consultas pesadas. Gracias a su estructura están especialmente diseñados para funciones de agregación como sumas, cálculos de valores promedio y en general cualquier operación que implique trabajar con datos de una sola columna. Sin embargo, esto que los hace buenos en entornos OLAP los hace especialmente malos en búsquedas de un valor concreto típicas de un entorno transaccional (OLTP). 

Conclusión

Hemos aprendido qué son y cómo se organizan los índices columnares. También podemos entender cuándo debemos usarlos. Para las tablas de hechos de nuestro datawarehouse lo mejor son los índices columnares clustered mientras que para la mayoría de entornos transaccionales no nos serán de ayuda. Sin embargo, en la vida real es común que los departamentos de análisis, además de trabajar sobre sus entornos OLAP, realicen consultas en caliente sobre entornos OLTP y es donde más partido podremos sacar de los índices columnares nonclustered. También para informes de las propias aplicaciones, no tenemos por qué irnos a informes de departamentos específicos.

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

Índices Nonclustered (Índices parte 4)

Continuamos nuestra serie de Índices en SQL Server. Después de una introducción y de profundizar en las tablas HEAP y los índices clustered ha llegado el turno de los índices nonclustered. Durante este blog vamos a profundizar en su funcionamiento, cuál es la mejor estrategia para crearlos y responderemos a la pregunta de si son buenos o malos para el rendimiento.

Estructura de un índice nonclustered

En la introducción de esta serie comentamos que los índices nonclustered son como una copia de la tabla que solo incluye las columnas que hemos elegido. Profundicemos en esto, un índice nonclustered se crea sobre las mismas páginas de 8Kb que el resto de objetos en SQL Server. En ellas se almacenan las columnas que hemos añadido al índice ordenadas ascendente o descendentemente según elijamos y un puntero hacia la ubicación física del resto de columnas de esas filas. Al igual que pasaba con los índices clustered sobre estas columnas se crea una estructura de árbol B o árbol invertido desde un nivel raíz hasta los datos. Podemos verlo en esta imagen sacada de la documentación oficial de Microsoft:

Cuando se crea un índice nonclustered sobre una tabla HEAP o una vista que no tenga un índice clustered (más sobre vistas indexadas aquí) el nivel de hoja contendrá el RID (identificador de fila) de las filas además de las columnas incluidas en el índice. Si por el contrario se crea sobre una tabla con un índice clustered, el nivel hoja incluirá las columnas del índice clustered. Adicionalmente, solo si el índice clustered no es único, se incluirá también un identificador de fila.

Filtrar por un índice nonclustered

Cuando filtras por una columna incluida en un índice nonclustered SQL Server buscará en ese índice los valores deseados. Independientemente de lo que pase después esto es mucho más rápido que leer la tabla completa en busca de un valor y se reduce en gran medida el consumo de recursos de E/S. Sin embargo aquí pueden pasar dos cosas, puede que nuestro índice incluya todas las columnas que deseamos recuperar en cuyo caso no habrá que leer más o puede que necesitemos más información de la que contiene el índice. En este caso, usará el puntero para saltar directamente a la ubicación de esos datos sin hacer lecturas innecesarias. Cuando un índice incluye todos los campos que requiere la consulta se dice que el índice cubre la consulta y es lo más óptimo en cuanto a rendimiento de lecturas.

Buenas prácticas 

Acabamos de ver que lo mejor para nuestras lecturas será que nuestro índice nonclustered cubra completamente nuestras consultas, sin embargo, todo tiene un pero. A mi me gusta comparar los índices nonclustered con la típica mantita que todos tenemos en el sofá, esa que si te tapas hasta arriba te deja los pies fuera y si te tapas los pies no te arropa hasta arriba. Igual que la mantita, nuestros índices tienen sus cosas malas y para arreglar una cosa empeoran otra. Como hemos comentado, los índices nonclustered son objetos separados de la tabla por lo que cada vez que escribamos (o modifiquemos) un dato en la tabla se tiene que modificar en todos los índices que contengan esa columna. Esto degrada el rendimiento de las escrituras.

Tenemos que tener esto muy en mente a la hora de diseñar los índices nonclustered ya que no nos podemos pasar creando índices nonclustered. Tampoco debemos crear índices nonclustered en columnas que tengan pocas lecturas por cada escritura o incluso más escrituras que lecturas.

Columnas clave o columnas incluidas

Si después de analizar todo esto aún nos cuadra el índice nonclustered, tenemos que tener en cuenta la limitación de 16 claves por índice. Tranquilos si no habéis entendido esto, he metido un concepto nuevo que ahora os explico.

Las columnas que forman parte de un índice nonclustered pueden ser claves o incluidas. Llamamos columnas clave a las columnas que forman parte del índice y por las que vamos a poder filtrar. Sin embargo para poder cubrir más consultas en ocasiones nos interesará añadir otras columnas al índice por las que no se va a filtrar pero si vamos a querer recuperar. Para esto tenemos la opción de incluir columnas. Es importante que no vayamos a filtrar por las columnas incluidas ya que estas no se van a escribir en los niveles raíz e intermedios de nuestro índice nonclustered y solo van a estar en el nivel hoja. Si antes decíamos que un índice nonclustered solo puede tener 16 columnas clave, como columnas incluidas podemos tener hasta 1023. 

¿Qué columnas añado a mi índice?

A estas alturas ya sabemos las implicaciones para el rendimiento de los índices y la teoría, llega el momento de ponernos a crearlo. Hemos visto que no es recomendable crear índices con claves muy largas así que, crearemos las columnas clave que normalmente se usan para filtrar o agrupar los datos (en el where, join, group by o having de nuestras consultas). Si necesitamos agregar alguna consulta más para cubrir completamente las consultas lo haremos dentro de la cláusula INCLUDE.

Conclusión

Hemos visto cómo funcionan los índices nonclustered y como son un arma de doble filo para el rendimiento de nuestra base de datos. Sin haberlo comentado hasta ahora, pero interiorizando los conceptos que hemos aprendido también vamos a ser capaces de entender por qué no es una buena idea añadir todas las columnas de nuestra tabla en un índice nonclustered. Otra enseñanza que nos llevamos es el hecho de qué si un índice nonclustered puede cubrir completamente las consultas hacer select * es una práctica a evitar si queremos mejorar el rendimiento. 

Contenido de la serie

Introducción a los índices en SQL Server (Índices parte 1)

Estructura física de las tablas y HEAP (Índices parte 2)

Índices Clustered y Primary Keys (Índices parte 3)

Índices Columnares (Índices parte 5)

Índices especiales (Índices parte 6)

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