Estadísticas supersíncronas

Estadísticas supersíncronas

En nuestro día a día cuando hablamos de estadísticas en SQL Server casi siempre nos centramos en la necesidad de su mantenimiento periódico, a la recomendación de mantener activas las actualizaciones automáticas de estadísticas y, salvo en ciertos casos, las ventajas de la actualización asíncrona de estadísticas. (más…)

Cazando vampiros de memoria en SQL Server

Cazando vampiros de memoria en SQL Server

Un recurso muy valioso para cualquier motor de base de datos es la memoria. Esta memoria se utilizará con muchos fines, destacando especialmente el cacheo de páginas/segmentos de datos, así como planes de ejecución. También se necesitará memoria para la propia ejecución de las consultas, para mantener temporalmente los buffers necesarios para el procesamiento de los datos, para su ordenación, para almacenar tablas hash, etc. Desgraciadamente no existe un punto único desde donde podamos determinar y diagnosticar todos los consumos de memoria independientemente de su naturaleza por lo que al final tendremos que ir analizando desde un punto de vista más alto hasta uno más bajo para poder poner el dedo exactamente en la llaga que origina el dolor al servidor. (más…)

Integridad referencial en SQL Server 2017 Graphs

Integridad referencial en SQL Server 2017 Graphs

En SQL Server 2017 se incorpora por primera vez en el motor de SQL Server el soporte nativo de grafos. En el SolidQ Summit 2018 impartí una sesión dedicada precisamente a mostrar en detalle esta nueva funcionalidad. En este post vamos a tratar cómo podemos añadir un workaround a una limitación de integridad que no se incluye por defecto y nos parece de bastante importancia.

(más…)

La importancia del connection pooling cuando usamos SSL/TLS sobre TDS

La importancia del connection pooling cuando usamos SSL/TLS sobre TDS

El uso de connection pooling es una técnica importante desde el punto de vista de rendimiento de SQL Server. Si cada petición que lanzáramos a la base de datos tuviera que pasar necesariamente por el proceso completo de conexión al servidor, con su autenticación, etc. el rendimiento sería muy pobre.

Desgraciadamente aún nos encontramos con aplicaciones, casi siempre heredadas, que no utilizan connection pooling y por tanto abren y cierran físicamente la conexión cada vez con la base de datos. Una buena forma de detectar si nuestras aplicaciones están utilizando o no connection pooling es analizando los contadores de rendimiento Login/sec y Logout/sec. Cuando estos valores sean elevados respecto al número de conexiones existentes entonces con una alta probabilidad estaremos teniendo este problema al menos en parte de las aplicaciones que conectan contra nuestro servidor.

En algunos casos extremos podemos tener valores elevados de estos valores si tenemos muchas aplicaciones que, aun utilizando pooling, generen picos de conexiones concurrentes elevadas. Esto hará que el tamaño del pool crezca para poder servir este número de conexiones que se necesitan de forma puntual, generando un pico de Login/sec. Pasado un tiempo de inactividad (por defecto suele ser 60 segundos) las conexiones se cerrarán por falta de uso generando un pico de Logout/sec. Si tenemos muchos clientes con este mismo comportamiento podemos llegar a tener, en todo momento, un número elevado de Login/sec y de Logout/sec causados por estas oscilaciones en los tamaños de los pools sin que realmente tengamos aplicaciones que no utilicen connection pooling. Este timeout de desconexión puede indicarse al proveedor vía cadena de conexión o también mediante configuración directa del proveedor.

En el caso de ODBC por ejemplo podemos controlar el pool timeout (CPTimeout) desde el administrador de Data Sources:

También tenemos casos en los que el mal uso del connection pooling es el problema de los problemas de rendimiento sufridos. Por ejemplo, imaginemos que para evitar el delay que ocurre cuando nos conectamos a un servidor a través de un pool y tenemos que abrir la conexión físicamente se decide configurar un mínimo de 100 conexiones abiertas en una aplicación cliente-servidor. Puede parecer excesiva esta medida, pero cuando la autenticación del usuario recae en Active Directory, tenemos muchos usuarios distintos y el AD se encuentra saturado o lejano geográficamente (y no tenemos AD secundarios locales) el proceso de login puede durar hasta varios segundos. Seguramente alguien se ha topado con este problema especialmente al intentar conectar con SQL Database desde el Microsoft SQL Management Studio. Por defecto el Microsoft SQL Management Studio utiliza 15 segundos como login timeout lo cual resulta insuficiente en ocasiones para completar el proceso de enrutado y login.

El problema de mantener un pool con un mínimo tan elevado de conexiones es que éstas no se cerrarán y si el número de usuarios de dicha aplicación cliente-servidor aumenta, el número de conexiones aumentará también de forma lineal. El límite de conexiones que una instancia de SQL Server puede aceptar es de 32767 por lo que con menos de 330 usuarios de la aplicación el servidor quedará saturado no aceptando más usuarios ni conexiones. Por tanto, la clave estará en configurar de forma equilibrada los valores mínimos para el pool de conexiones, el valor máximo y el tiempo que dichas conexiones permanecerán abiertas.

Una vez introducida la importancia del buen uso del connection pooling queremos mostrar otro escenario que puede amplificar más aún el impacto de no utilizar connection pooling. Concretamente un cliente nos contactó con problemas de rendimiento derivados de la activación de la encriptación SSL de las conexiones con SQL Server. No es habitual encontrarnos con este tipo de problemas ya que, aunque la encriptación SSL tiene un coste extra, en general es asumible y no supone más que un pequeño incremento en el consumo de CPU total del servidor. Sin embargo, en este caso el consumo de CPU no era excesivo y los tiempos de ejecución de las consultas similares, pero sin embargo lo que sí teníamos eran ralentizaciones durante el proceso de conexión. Por tanto, el problema de rendimiento era debido a esperas durante el proceso de conexión a la base de datos una vez se habilitaba y forzaba el uso de SSL.

Para verificar que efectivamente existe un impacto medible realizamos una prueba de concepto donde estresaríamos una máquina virtual para comprobar el impacto de forzar la encriptación SSL. El primer paso es configurar SQL Server con un certificado SSL apropiado para ello. Es importante que el certificado cumpla ciertas condiciones ya que en caso contrario no será aceptado. En la sección de troubleshooting de este artículo podemos encontrar más información: (https://support.microsoft.com/en-us/help/316898/how-to-enable-ssl-encryption-for-an-instance-of-sql-server-by-using-mi)

Aunque nos salgamos un poco de contexto es conveniente indicar que este certificado no tiene nada que ver con el que necesitaríamos por ejemplo para una encriptación TDE. Para poder encriptar con TDE necesitaríamos un certificado obtenido siguiendo el siguiente proceso: https://blogs.msdn.microsoft.com/sql_pfe_blog/2014/02/04/generating-a-trusted-tde-certificate-in-the-proper-format-from-a-certificate-authority/ Si tuviéramos que reutilizar un pfx existente habría que hacer una conversión con esta herramienta para adaptarlo al formato requerido: https://support.microsoft.com/en-ph/help/2914662/how-to-use-pfx-formatted-certificates-in-sql-server

Para la prueba de concepto crearemos un certificado autofirmado con este comando powershell:

Con este comando el certificado creado se cargará en el store “personal”:

 

Para que la validez del certificado pueda ser validada tendremos que exportar dicho certificado e importarlo dentro la carpeta con los certificados raíz de confianza. Normalmente este proceso no será necesario ya que el certificado que utilicemos vendrá de una fuente de certificación de confianza:

Antes de forzar el uso de encriptación realizaremos una prueba donde lanzaremos una consulta extremadamente sencilla con 50 threads y 100 iteraciones. Antes de lanzar la carga configuraremos la conexión a la base de datos sin connection pooling:

Podemos ver que sin encriptación SSL tenemos un tiempo total de ejecución de 14 segundos y un tiempo de respuesta medio de 9 milisegundos que nos servirá como línea base cuando comparemos con el entorno con SSL. Si monitorizamos el número de logins por segundo que alcanzamos podemos ver que llegamos a un pico de 450 por segundo:

Para configurar la encriptación SSL abriremos el Configuration Manager de SQL Server y en la sección “protocols” editaremos sus propiedades y activaremos el flag para forzar la encriptación de las conexiones:

En la pestaña “certificate” seleccionaremos el certificado que hemos creado previamente y reiniciaremos el servicio de SQL Server:

Antes de lanzar la carga comprobaremos que efectivamente las conexiones que realicemos contra el servidor están efectivamente encriptadas consultando la DMV sys.dm_exec_connections:

El siguiente paso será volver a lanzar la carga anterior contra el servidor:

Podemos ver que el tiempo total ha subido a casi 19 segundos (un 35% más) y el tiempo medio por ejecución de 9ms a 46ms. En lo que respecta al número de conexiones por segundo que podemos procesar vemos que se estancan en menos de 300 (vs las 450 que alcanzábamos sin SSL):

Queda por tanto claro que el número de conexiones por segundo que podemos abrir depende de forma importante de si habilitamos el SSL o no. En casos donde no tengamos paralelismo o éste sea más moderado las latencias por conexión pueden tener un impacto mucho mayor ya que el aumento de la latencia será más significativo. En el siguiente gráfico mostramos un caso real donde podemos ver que pasamos de tiempos de 10 segundos para un proceso serial sin SSL a más de 30 segundos con el SSL activado para el mismo proceso:

En conclusión, en condiciones normales, donde el connection pooling es utilizado de forma correcta, el uso de SSL no supone una sobrecarga relevante ni genera problemas. Sin embargo, donde ya teníamos una situación problemática previa (no uso de connection pooling y un proceso serial)  la activación de SSL sí puede empeorar la situación de forma notable. Recomendamos por tanto antes de habilitar a ciegas el SSL realizar una revisión previa del servidor para asegurarnos que no tenemos ya un problema previo que pudiera verse amplificado con su activación.

Curiosidades con Heaps y entornos con alto consumo de CPU

Curiosidades con Heaps y entornos con alto consumo de CPU

Es bastante habitual encontrarnos con el siguiente diálogo al aterrizar en un cliente:

  • SolidQ: ¿Me puedes comentar o mostrar los gráficos del consumo de CPU del servidor X?
  • Cliente: De CPU vamos bien, no es problema.
  • SolidQ: Si no te importa, ¿puedes mostrarme los datos que tienes al respecto?
  • Cliente: Claro. Mira, aquí puedes ver que tenemos medias (en periodos de 5 minutos) del 60% de CPU y en los momentos de más carga no pasamos del 85% de media. Está correcto, ¿verdad?

El problema de esta aproximación a la hora de interpretar a la utilización de recursos es que, intuitivamente, no solemos ser conscientes de qué implicaciones tienen estos grados de utilización tan altos. No debemos confundir la interpretación respecto a la que tendríamos del % de uso de memoria o del % de uso de disco, que únicamente indican cuanta cantidad de memoria/espacio estamos utilizando, pero no el grado de utilización de dicho recurso.

(más…)

Buscando las cosquillas al heartbeat de Windows Clustering

Buscando las cosquillas al heartbeat de Windows Clustering

A día de hoy el sistema de alta disponibilidad más utilizado para SQL Server sigue siendo aún Failover Clustering. Uno de los componentes críticos para el buen funcionamiento del clúster es el mantener unas comunicaciones entre los nodos de calidad. Concretamente con calidad nos referimos a que no tengamos cortes, descartes de paquetes o latencias excesivas para el tráfico de heartbeat.

(más…)

SQL Server 2016: sys.dm_exec_session_wait_stats y sys.dm_exec_query_optimizer_memory_gateways

SQL Server 2016: sys.dm_exec_session_wait_stats y sys.dm_exec_query_optimizer_memory_gateways

En este post me gustaría comentar un par de pequeñas gemas que aparecen en SQL Server 2016 y que nos pueden ayudar mucho a los que nos dedicamos al troubleshooting y la optimización. La primera de ellas nos proporciona información de las esperas desglosada a nivel de sesión. Esta funcionalidad en versiones anteriores la podíamos simular mediante el uso de eventos extendidos, aunque resultaba bastante arduo. Para quien pueda estar interesado o no disponga de SQL Server 2016 en el blog de Paul Randal podéis ver un ejemplo de cómo podemos crear dicha sesión: http://www.sqlskills.com/blogs/paul/capturing-wait-stats-for-a-single-operation/

(más…)

Una historia de fragmentación, particionado e índices columnares

Una historia de fragmentación, particionado e índices columnares

Resulta bastante habitual encontrarnos en muchos clientes situaciones de mal uso de funcionalidades de SQL Server, especialmente cuando existe cierto “hype” alrededor de ellas. Sin embargo, algo que todo técnico/arquitecto debería evaluar siempre son los pros y contras de las decisiones que se toman así como realizar mediciones para asegurarse que no tenemos algún efecto indeseado imprevisto. Todos sabemos que, en las presentaciones de productos tecnológicos, cuando se exponen las nuevas características, etc. se “vende la moto” sin entrar en los detalles y casi nada en esta vida es gratis o está exento de contras. (más…)

“To shrink or not to shrink” esa es la cuestión

“To shrink or not to shrink” esa es la cuestión

En ocasiones nos encontramos en situaciones donde el espacio libre en un disco se ha reducido tanto que nos genera errores de asignación en nuestras bases de datos. En esos momentos, normalmente con cierta urgencia, un posible recurso es realizar una operación de shrink para liberar espacio al final de los ficheros. El problema es que, en función de la existencia o no de datos al final del fichero, esta operación puede ser muy costosa y lenta.

(más…)