sql >> Base de Datos >  >> RDS >> Database

Un enfoque para el ajuste de índice - Parte 1

Un compromiso de ajuste del rendimiento puede terminar tomando muchas vueltas a medida que lo resuelve; todo depende de lo que se muestre como el problema y lo que le indiquen los datos. Algunos días aterriza en una consulta específica, o un conjunto de consultas, que se pueden mejorar con índices, ya sean nuevos o modificaciones a los índices existentes. Una de mis partes favoritas de la afinación es trabajar con índices y, mientras pensaba en esta publicación, tuve la tentación de etiquetar la afinación de índices como una tarea "más fácil"... pero en realidad no lo es.

Pienso en el ajuste de índices como un arte y una ciencia. Debe intentar pensar como el optimizador, y debe comprender el esquema de la tabla y la consulta (o consultas) que está tratando de ajustar. Ambos están basados ​​en datos y, por lo tanto, en la categoría de ciencia. El componente artístico entra en juego cuando piensas en el otro índices en la tabla y todos el otro consultas que involucran la tabla que podría verse afectada por cambios en el índice.

Paso 1:identificar la consulta y revisar el plan

Cuando identifico una consulta que podría beneficiarse de un índice, obtengo inmediatamente su plan. A menudo obtengo el Plan de ejecución de la memoria caché del plan o del Almacén de consultas, y luego uso SSMS para obtener el Plan de ejecución más las Estadísticas de tiempo de ejecución (también conocido como Plan de ejecución real). Muchas veces, la forma de esos dos planos es la misma; pero no es una garantía, por eso me gusta ver ambos.

El plan puede tener una recomendación de índice faltante, puede tener un análisis de índice agrupado (o un análisis de montón si no hay un índice agrupado), puede usar un índice no agrupado pero luego tener una búsqueda para recuperar columnas adicionales. Solucionar cada uno de esos problemas individualmente suena bastante fácil. Simplemente agregue el índice que falta, ¿verdad? Si hay un escaneo de un índice agrupado o un montón, ¿crear el índice que necesito para la consulta y listo? O si se está usando un índice pero va a la tabla para obtener las columnas adicionales, ¿simplemente agregue las columnas a ese índice?

Por lo general, no es tan fácil, e incluso cuando lo es, sigo pasando por el proceso que estoy describiendo aquí.

Paso 2:Determine qué tabla(s) revisar

Ahora que tengo mi consulta, tengo que averiguar qué tablas no están indexadas correctamente. Además de revisar el plan, también habilito las estadísticas IO y TIME en SSMS. Probablemente esto sea de mi vieja escuela, ya que los planes de ejecución contienen más y más información, incluida la duración y los números de IO por operador, con cada versión, pero me gustan las estadísticas de IO porque puedo ver rápidamente las lecturas de cada tabla. Para consultas que son complejas con múltiples uniones, subconsultas, CTE o vistas anidadas, comprender dónde se gasta el IO y/o el tiempo en las unidades de consulta donde paso mi tiempo. Siempre que sea posible desde este punto, tomo la consulta más grande y compleja y la reduzco a la parte que está causando el mayor problema.

Por ejemplo, si hay una consulta que se une a 10 tablas y tiene dos subconsultas, el plan (junto con la información de IO y duración) me ayuda a identificar dónde existe el problema. Luego sacaré esa parte de la consulta, la tabla problemática y tal vez un par de otras a las que se une, y me concentraré en eso. A veces es solo la subconsulta, así que empiezo allí.

Paso 3:mira los índices existentes

Con la consulta (o parte de la consulta) definida, me enfoco en los índices existentes para las tablas involucradas. Para este paso, confío en la versión de sp_helpindex de Kimberly. Prefiero su versión al sp_helpindex estándar porque también enumera las columnas INCLUIDAS y la definición del filtro (si existe). Dependiendo de la cantidad de índices que aparecen para una tabla, a menudo copio esto y lo pego en Excel, y luego lo ordeno según la clave del índice y luego las columnas incluidas. Esto me permite encontrar redundancias rápidamente.

Según el resultado del ejemplo anterior, hay siete índices que comienzan con CompanyID, cinco que comienzan con AcctNumber y algunas otras posibles redundancias. Si bien parece ideal tener solo uno índice que conduce a una columna en particular (por ejemplo, CompanyID), para algunos patrones de consulta que no es suficiente.

Cuando miro los índices existentes, es muy fácil caer en una madriguera de conejo. Veo el resultado anterior e inmediatamente empiezo a preguntar por qué hay siete índices que comienzan con CompanyID, y quiero saber quién los creó, por qué y para qué consulta. Pero… si mi consulta problemática no usa CompanyID, ¿debería importarme? Sí... porque en general estoy ahí para mejorar el rendimiento, y si eso significa mirar otros índices en la tabla en el camino, que así sea. Pero aquí es donde es fácil perder la noción del tiempo (y el verdadero propósito).

Si mi consulta problemática necesita un índice que lleve a PaidDate, solo tengo que lidiar con un índice existente. Si mi consulta problemática necesita un índice que lleve a AcctNumber, se vuelve complicado. Cuando los índices existentes cubren una consulta y busco expandir un índice (agregar más columnas) o consolidar (combinar dos o tal vez tres índices en uno), entonces tengo que profundizar.

Paso 4:Estadísticas de uso del índice

Me parece que mucha gente no captura las estadísticas de uso del índice de forma continua. Esto es desafortunado, porque encuentro que los datos son útiles para decidir qué índices mantener y cuáles descartar o fusionar. En el caso de que no tenga estadísticas de uso históricas, al menos verifico cómo se ve el uso actualmente (desde el último reinicio del servicio):

SELECT 
  	DB_NAME(ius.database_id),
  	OBJECT_NAME(i.object_id) [TableName],
  	i.name [IndexName],
  	ius.database_id,
  	i.object_id,
  	i.index_id, 
  	ius.user_seeks,
  	ius.user_scans,
  	ius.user_lookups,
  	ius.user_updates 
  FROM sys.indexes i
  INNER JOIN sys.dm_db_index_usage_stats ius 
  	ON ius.index_id = i.index_id AND ius.object_id = i.object_id
  WHERE ius.database_id = DB_ID(N'Sales2020')
  	AND i.object_id = OBJECT_ID('dbo.tblSales');

Nuevamente, me gusta poner esto en Excel, ordenar por búsquedas y luego escanear, y también tomar nota de las actualizaciones. Para este ejemplo, los índices en rojo son aquellos sin búsquedas, escaneos o búsquedas... solo actualizaciones. Esos son candidatos para ser deshabilitados y potencialmente eliminados, si realmente no se usan (nuevamente, tener un historial de uso ayudaría aquí). Los índices en verde definitivamente se están utilizando, quiero mantenerlos (aunque quizás en algunos casos podrían modificarse). Los que están en amarillo... algunos se están usando, otros apenas se están usando. Una vez más, el historial sería útil aquí, o el contexto de otros; a veces, un índice puede ser crucial para un informe o proceso que no se ejecuta todo el tiempo.

Si solo busco modificar o agregar un nuevo índice, en lugar de una limpieza y consolidación verdaderas, lo que más me preocupa son los índices que son similares a los que quiero agregar o cambiar. Sin embargo, me aseguraré de señalar la información de uso al cliente y, si el tiempo lo permite, ayudaré con la estrategia general de indexación de la tabla.

¿Qué sigue?

¡No hemos terminado! Esta es la parte 1 de mi enfoque para el ajuste de índices, y mi próxima entrega enumerará el resto de mis pasos. Mientras tanto, si no está capturando las estadísticas de uso del índice, eso es algo que puede implementar utilizando la consulta anterior u otra variación. Recomendaría capturar estadísticas de uso para todas las bases de datos de los usuarios, no solo una tabla y una base de datos específicas como lo hice anteriormente, así que modifique el predicado según sea necesario. Y finalmente, como parte de ese trabajo programado para tomar una instantánea de esa información en una tabla, no olvide otro paso para limpiar la tabla después de que los datos hayan estado allí por un tiempo (lo conservo durante al menos seis meses; algunos podrían decir que un año es necesario).