sql >> Base de Datos >  >> RDS >> Sqlserver

Cierres de SQL Server:otros cierres que debe conocer

Para terminar mi breve serie de artículos sobre pestillos, esta vez voy a discutir algunos otros pestillos en SQL Server que puede ver ocasionalmente pero que no merecen un artículo completo por sí solos. Como de costumbre, le recomiendo encarecidamente que lea la publicación inicial de la serie antes de esta, para que tenga todos los conocimientos generales sobre pestillos.

El pestillo LOG_MANAGER

El pestillo LOG_MANAGER se usa para la sincronización durante algunas operaciones que involucran el registro de transacciones, y hay un pestillo LOG_MANAGER por base de datos (ya que cada base de datos tiene su propio administrador de registros). Solo se puede adquirir en modo exclusivo y puede ser un cuello de botella durante el crecimiento del archivo de registro de transacciones. El escenario donde se hará evidente como un problema es:

  • El archivo de registro tiene un pequeño conjunto de crecimiento automático
  • Hay muchas conexiones simultáneas que generan registros de transacciones
  • El archivo de registro sigue teniendo que crecer

Cuando el archivo de registro se quede sin espacio, deberá crecer. El primer subproceso para darse cuenta de que se requiere más espacio de registro adquiere el latch LOG_MANAGER en modo EX y procede a hacer crecer el archivo de registro. Muchos otros subprocesos continúan intentando generar registros y entrar en la cola para el pestillo LOG_MANAGER, para que puedan hacer crecer el archivo de registro. Cuando el primer subproceso libera el pestillo, el siguiente lo obtiene y se da cuenta de que el registro ya ha crecido, por lo que lo suelta y continúa. Y así sucesivamente y así sucesivamente. Por cierto, este patrón de cuello de botella se denomina convoy de trabas. .

Puede pensar que es exactamente el mismo cuello de botella que con el pestillo FGCB_ADD_REMOVE que mencioné anteriormente en la serie, pero con un crecimiento del archivo de registro en lugar del crecimiento del archivo de datos. Sin embargo, con el pestillo FGCB_ADD_REMOVE, por lo general, la instancia tiene habilitada la inicialización instantánea de archivos, por lo que el crecimiento del archivo es muy rápido, pero con el pestillo LOG_MANAGER, el registro *debe* inicializarse en cero y el tiempo perdido en la cola del pestillo es más largo. .

La solución para este cuello de botella consta de tres partes:

  1. Establezca el crecimiento automático del archivo de registro correctamente, para que el registro no crezca con frecuencia
  2. Dimensione el registro correctamente para la carga de trabajo, por lo que el registro no debe crecer en absoluto
  3. Asegúrese de que el registro se esté borrando correctamente, para que el registro no necesite crecer

Si todo esto está en su lugar, no debería ver que el pestillo LOG_MANAGER sea un cuello de botella normal, y hablo más sobre esto en mi publicación aquí.

El pestillo ACCESS_METHODS_DATASET_PARENT

Cuando se accede a un montón o a un índice, internamente hay un objeto llamado HeapDataSetSession o IndexDataSetSession, respectivamente. Cuando se realiza un escaneo paralelo, los subprocesos que realizan el trabajo real del escaneo tienen cada uno un conjunto de datos "secundario" (otra instancia de los dos objetos que acabo de describir), y el conjunto de datos principal, que realmente controla el escaneo, se llama el "padre".

Cuando uno de los subprocesos de trabajo de escaneo ha agotado el conjunto de filas que se supone que debe escanear, necesita obtener un nuevo rango accediendo al conjunto de datos principal, lo que significa adquirir el pestillo ACCESS_METHODS_DATASET_PARENT en modo exclusivo. Si bien esto puede parecer un cuello de botella, en realidad no lo es, y no hay nada que pueda hacer para evitar que los subprocesos que realizan un escaneo paralelo muestren ocasionalmente una espera LATCH_EX para este pestillo.

La pregunta que debe hacerse es:¿esta consulta debería realizar un escaneo paralelo en primer lugar? Es muy posible que haya ocurrido algo que obligue al plan de consulta a incluir un escaneo paralelo cuando esa puede no ser la forma más eficiente de ejecutar la consulta. Ejemplos de cosas que podrían causar que un plan cambie a un escaneo paralelo incluyen:

  • Estadísticas desactualizadas
  • Un índice no agrupado faltante o descartado
  • Código nuevo que obliga a escanear debido a una conversión implícita:una falta de coincidencia del tipo de datos entre una columna y una variable/parámetro, lo que impide el uso de un índice no agrupado.
  • Nuevo código que fuerza un escaneo porque la aritmética se realiza en una columna de la tabla en lugar de una variable/parámetro, lo que de nuevo impide el uso de un índice no agrupado
  • Se está produciendo un crecimiento de los datos y un análisis es realmente el plan más eficiente

O podría ser que esta consulta requiera un análisis, en cuyo caso LATCH_EX espera que ACCESS_METHODS_DATASET_PARENT sean solo parte de su entorno.

El pestillo ACCESS_METHODS_HOBT_VIRTUAL_ROOT

Cada instancia de este pestillo protege una entrada en los metadatos del motor de almacenamiento para un árbol b, específicamente el ID de página de la página raíz del árbol b (la página en la parte superior del triángulo que generalmente consideramos un índice) . Estoy diciendo específicamente b-tree y no índice , ya que un índice puede tener varias particiones, cada una de las cuales tiene un árbol B (esencialmente una parte del índice general, pero con restricciones de clave de valor bajo y valor alto).

Cada vez que un subproceso necesita atravesar un árbol b, debe comenzar en la página raíz y avanzar hasta el nivel de la hoja. Para leer los metadatos que contienen el ID de página de la página raíz, el subproceso debe adquirir el pestillo ACCESS_METHODS_HOBT_VIRTUAL_ROOT en modo SH, para asegurarse de que el ID de página no esté en proceso de cambio. Cuando un subproceso necesita cambiar el ID de página de la página raíz, debe adquirir el pestillo en modo EX.

¿Por qué cambiaría la página raíz de un árbol b? A medida que crece el número de registros de índice en la página raíz, eventualmente se llenará y se producirá una división de página. Cuando eso sucede, la página raíz actual y la página en la que se divide se convierten en un nuevo nivel en el árbol b, y se crea una página raíz completamente nueva, con dos registros de índice que apuntan a la página raíz anterior y la página en la que se encuentra. dividido en. La nueva ID de la página raíz debe ingresarse en los metadatos, por lo que el pestillo se adquiere en modo EX. Esto sucederá varias veces rápidamente cuando un índice en una tabla vacía comience a llenarse con inserciones, pero no es algo que verá como un problema continuo de cuello de botella en el rendimiento.

Resumen

Como estoy seguro de que ha deducido de esta serie, comprender los bloqueos y los cuellos de botella de los bloqueos implica saber un poco más sobre lo que sucede dentro del motor de almacenamiento que para el análisis general de estadísticas de espera.

Por lo general, aconsejo a las personas que *no* comiencen a solucionar problemas de rendimiento mirando las estadísticas de latch (a través de sys.dm_os_latch_stats ) pero en su lugar siempre comenzar con las estadísticas de espera (ver mi publicación aquí) y solo profundizar en los latches si LATCH_EX o LATCH_SH son una de las principales esperas en la instancia de SQL Server.

Si tiene alguna pregunta sobre los pestillos, no dude en escribirme.