Database
 sql >> Base de données >  >> RDS >> Database

Couper la graisse du journal des transactions

Dans de nombreuses charges de travail SQL Server, en particulier OLTP, le journal des transactions de la base de données peut constituer un goulot d'étranglement qui augmente le temps nécessaire à l'exécution d'une transaction. La plupart des gens supposent que le sous-système d'E/S est le véritable goulot d'étranglement, car il n'est pas en mesure de suivre la quantité de journaux de transactions générés par la charge de travail.

Latence d'écriture du journal des transactions

La latence des opérations d'écriture dans le journal des transactions peut être surveillée à l'aide de sys.dm_io_virtual_file_stats DMV et corrélé avec le WRITELOG attentes qui se produisent sur le système. J'ai enregistré une vidéo de démonstration de l'analyse des E/S du journal des transactions en 2011, je ne répéterai donc pas tout cela dans cet article. Vous pouvez obtenir la vidéo ici et le code de démonstration ici (convient pour une exécution immédiate en production).

Si la latence d'écriture est supérieure à ce à quoi vous vous attendiez pour votre sous-système d'E/S, le sous-système d'E/S ne peut pas suivre, comme c'est généralement le cas. Cela signifie-t-il que le sous-système d'E/S doit être amélioré ? Pas nécessairement.

Sur de nombreux systèmes clients, j'ai constaté qu'une proportion importante d'enregistrements de journaux générés sont inutiles, et si vous pouvez réduire le nombre d'enregistrements de journaux générés, vous réduisez la quantité de journaux de transactions écrits sur le disque. Cela devrait se traduire par une réduction de la latence d'écriture, réduisant ainsi le temps d'achèvement des transactions.

Il existe deux principales causes de génération d'enregistrements de journaux superflus :les index non clusterisés inutilisés et la fragmentation des index.

Index non clusterisés inutilisés

Chaque fois qu'un enregistrement est inséré dans une table, un enregistrement doit être inséré dans chaque index non cluster défini sur la table (à l'exception des index filtrés avec des filtres appropriés, que j'ignorerai à partir de ce point). Cela signifie que des enregistrements de journal supplémentaires sont générés, au moins un par index non clusterisé, pour chaque insertion de table. La même chose s'applique à la suppression d'un enregistrement dans une table - les enregistrements correspondants doivent être supprimés de tous les index non clusterisés. Pour une mise à jour d'un enregistrement de table, les enregistrements d'index non cluster sont mis à jour uniquement si la ou les colonnes de clé d'index non cluster ou les colonnes incluses faisaient partie de la mise à jour.

Ces opérations sont nécessaires, bien sûr, pour que chaque index non clusterisé soit correct par rapport à la table, mais si l'index non clusterisé n'est pas utilisé par la charge de travail, les opérations et les enregistrements de journal qu'elles produisent représentent une surcharge inutile. De plus, si ces index inutilisés deviennent fragmentés (ce dont je parlerai plus tard dans cet article), les tâches régulières de maintenance des index fonctionneront également sur eux, générant encore plus d'enregistrements de journal (à partir de l'index REBUILD ou REORGANIZE opérations) complètement inutilement.

Les index inutilisés proviennent d'une variété de sources telles que quelqu'un créant par erreur un index par colonne de table, quelqu'un créant chaque index suggéré par les DMV d'index manquants ou quelqu'un créant tous les index suggérés par le Database Tuning Advisor. Il se peut également que les caractéristiques de la charge de travail aient changé et que des index autrefois utiles ne soient plus utilisés.

D'où qu'ils viennent, les index inutilisés doivent être supprimés pour réduire leur surcharge. Vous pouvez déterminer quels index sont inutilisés à l'aide du DMV sys.dm_db_index_usage_stats, et je vous recommande de lire les articles de mes collègues Kimberly L. Tripp (ici) et Joe Sack (ici et ici), car ils expliquent comment utiliser correctement le DMV.

Fragmentation de l'index

La plupart des gens pensent que la fragmentation des index est un problème qui affecte les requêtes qui doivent lire de grandes quantités de données. Bien qu'il s'agisse de l'un des problèmes que la fragmentation peut causer, la fragmentation est également un problème en raison de la façon dont elle se produit.

La fragmentation est causée par une opération appelée fractionnement de page. La cause la plus simple d'un fractionnement de page est lorsqu'un enregistrement d'index doit être inséré sur une page particulière (en raison de sa valeur de clé) et que la page ne dispose pas de suffisamment d'espace libre. Dans ce scénario, les opérations suivantes auront lieu :

  • Une nouvelle page d'index est allouée et formatée
  • Certains des enregistrements de la page complète sont déplacés vers la nouvelle page, créant ainsi de l'espace libre dans la page requise
  • La nouvelle page est liée à la structure de l'index
  • Le nouvel enregistrement est inséré sur la page requise

Toutes ces opérations génèrent des enregistrements de journal, et comme vous pouvez l'imaginer, cela peut être beaucoup plus que nécessaire pour insérer un nouvel enregistrement sur une page qui ne nécessite pas de fractionnement de page. En 2009, j'ai publié sur un blog une analyse du coût du fractionnement de page en termes de journal des transactions et j'ai trouvé des cas où un fractionnement de page générait plus de 40 fois plus de journal des transactions qu'un encart normal !

La première étape pour réduire le coût supplémentaire consiste à supprimer les index inutilisés, comme je l'ai décrit ci-dessus, afin qu'ils ne génèrent pas de fractionnements de page. La deuxième étape consiste à identifier les index restants qui sont en train de se fragmenter (et doivent donc subir des fractionnements de page) à l'aide de sys.dm_db_index_physical_stats DMV (ou le nouveau SQL Sentry Fragmentation Manager) et en créant de manière proactive de l'espace libre à l'aide d'un facteur de remplissage d'index. Un facteur de remplissage indique à SQL Server de laisser un espace vide sur les pages d'index lorsque l'index est construit, reconstruit ou réorganisé afin qu'il y ait de l'espace pour permettre l'insertion de nouveaux enregistrements sans nécessiter de fractionnement de page, réduisant ainsi les enregistrements de journal supplémentaires générés.

Bien sûr, rien n'est gratuit - le compromis lors de l'utilisation de fillfactors est que vous provisionnez de manière proactive de l'espace supplémentaire dans les index pour éviter que davantage d'enregistrements de journal ne soient générés - mais c'est généralement un bon compromis à faire. Choisir un facteur de remplissage est relativement facile et j'en ai parlé ici.

Résumé

Réduire la latence d'écriture d'un fichier journal des transactions ne signifie pas toujours passer à un sous-système d'E/S plus rapide ou séparer le fichier dans sa propre partie du sous-système d'E/S. Avec une simple analyse des index de votre base de données, vous pourrez peut-être réduire considérablement le nombre d'enregistrements de journaux de transactions générés, ce qui entraînera une réduction proportionnelle de la latence d'écriture.

Il existe d'autres problèmes plus subtils qui peuvent affecter les performances du journal des transactions, et je les explorerai dans un prochain article.