Il peut arriver qu'une petite quantité de données atteigne une certaine limite dans SQL Server pour forcer un autre plan ou quelque chose comme ça. Ce n'est pas improbable. Mais le fait que votre disque semble être lourdement contraint m'amène à une autre conclusion.
Il y a 2 raisons possibles à votre ralentissement.
- Vous avez mis à niveau votre système et l'avez redémarré
- Vous y chargez un tas de données
Jetons un coup d'œil à la partie n ° 1
Il se peut que votre configuration SQL Server soit rompue. Cela peut entraîner de graves problèmes concernant la vitesse de votre serveur et l'utilisation du disque.
Veuillez vérifier en premier lieu les paramètres de base de votre serveur. Ces réglages de base sont max server memory
, affinity I/O mask
, affinity mask
et max degree of parallelism
. Vous devrez peut-être activer les options avancées à l'aide de show advanced options
.
Voici un script complet:
-- enable advanced options
EXEC sp_configure 'show advanced options',1
-- apply configuration
RECONFIGURE
-- how much memory can the sql server allocate?
EXEC sp_configure 'max server memory'
-- which cpu is used to run I/O operations
EXEC sp_configure 'affinity I/O mask'
-- which cpus can run processes?
EXEC sp_configure 'affinity mask'
-- how many threads can work on one query part?
EXEC sp_configure 'max degree of parallelism'
Comparez le résultat avec vos valeurs documentées dans vos étapes d'installation. Sont-ils toujours les mêmes?
Il peut y avoir plusieurs raisons pour lesquelles votre serveur se comporte si étrangement. Je parierais normalement que vous vous max server memory
trompez. Cela entraînera l'échange de pages de données de votre serveur SQL en permanence. Il ne peut pas tout garder en mémoire. Cela signifie qu'il doit lire les pages du disque, le mettre à jour, le réécrire instantanément. Si une autre mise à jour arrive et utilise la même page pour une mise à jour, elle ne peut pas être lue dans la mémoire. Au lieu de cela, le serveur doit le relire à partir du disque. Échange juste ...
Un autre problème peut être lié à une affinité élevée sur le disque ou les processus. Si vous avez utilisé un serveur partagé (SQL Server + autres services) avec un disque dédié pour SQL Server (ce qui peut être un cas rare, mais cela pourrait l'être), cela pourrait être votre problème. Votre serveur avait normalement par exemple 3 processeurs pour les processus et un pour les E / S. Les 12 autres CPU sont utilisés pour d'autres services. Dans ce cas, votre masque d'affinité est incorrect et utilise par exemple une configuration automatique. Cela signifie que votre serveur utilise les 16 cœurs pour les processus et les E / S de manière dynamique. Si vous avez d'énormes processus en cours d'exécution, ils peuvent mettre une énorme charge sur le disque, qu'il ne peut pas gérer. Mais en fait, je ne pense pas que ce soit votre cas. Ce serait plus rapide (même si c'est juste un peu) si cela s'appliquait, mais votre cas est un ralentissement.
Un autre problème peut être un degré de parallélisme trop élevé. Ce qui signifie que vous avez trop de threads au ralenti sur une partie d'une requête. Cela pourrait également provoquer un énorme ralentissement si le parallélisme ne fonctionne pas comme prévu. Mais cela ne décrira pas votre total d'E / S élevées.
Jetons maintenant un œil à la partie n ° 2 également
Vous chargez un tas de lignes dans votre système. Même s'il s'agit d'un travail normal, cela pourrait augmenter la limite dans laquelle vos plans de requête s'intensifient. Il se peut même que votre insertion en combinaison avec SQL Server produise ce comportement.
Vous avez mentionné que vous avez déjà essayé de migrer vos index vers un autre disque, ce qui semble vous aider. Cela peut être dû au fait que vous divisez la charge sur deux disques différents.
Il se peut que vos indices aient été fracturés, que vos plans aient été fracturés ou que vos statistiques soient juste dépassées.
1. permet de vérifier les dernières mises à jour des statistiques
Vous pouvez le faire manuellement via l'interface pour chaque élément statistique unique. Ce serait une douleur. Ou vous pouvez essayer ce code:
SELECT name AS indexname,
STATS_DATE(OBJECT_ID, index_id) AS StatsUpdated
FROM sys.indexes
Cela vous donnera une information complète sur chaque index (et tas) et les statistiques derrière eux. Même si vous l'exécutez, sp_updatestats
cela ne signifie pas que les statistiques ont été mises à jour. La partie lorsqu'une mise à jour est assez délicate, même si vous exécutez sp_updatestats
ou même si elle auto update statistics
est activée, les statistiques ne seront pas mises à jour juste à temps. Voici quelques points marginaux, lorsqu'une mise à jour est nécessaire / générée:
- Une table vide obtient une ou plusieurs lignes
- Un tableau avec plus de 500 lignes met à jour 20% + 500 lignes supplémentaires et une insertion s'est produite par la suite
- Lorsque 500 lignes ont été modifiées dans une table contenant moins de 500 lignes
Cela signifie que vos statistiques peuvent être obsolètes même si vous exécutez la mise à jour.
Vous pouvez jeter un œil à la requête ci-dessus. Si vous trouvez des statistiques assez anciennes dans certains tableaux, vous souhaiterez peut-être exécuter une mise à jour manuelle des statistiques pour ce tableau:
UPDATE STATISTICS dbo.YourBadTable WITH FULLSCAN
Après cela, vous voudrez peut-être donner un coup de pied à votre serveur pour jeter tous les anciens plans.
DBCC FREEPROCCACHE
Si vous souhaitez simplement nettoyer tous les caches, vous pouvez exécuter ceci à la place:
DBCC FREESYSTEMCACHE ('ALL')
Cela nettoiera tous les caches, pas seulement le cache du plan. Je préviens normalement, d'utiliser ceci sur un serveur de production en phase de production. Mais comme votre serveur ne fonctionne pas actuellement, vous ne pouvez pas trop leur faire de mal. Cela peut ralentir pendant quelques secondes, peut-être 1-2 minutes, car il doit reconstruire tous les caches, mais après cela, il devrait exécuter les bons plans.
Une autre raison peut être les indices totalement fragmentés. Cela peut être vérifié sur l'ensemble du serveur à l'aide de cette instruction:
SELECT *
FROM sys.dm_db_index_physical_stats (NULL, NULL, NULL, NULL, NULL)
Si la fragmentation est très élevée, vous devrez peut-être la réorganiser (fragmentation <20%) ou la reconstruire totalement (> 20%). Cela peut augmenter la pression sur votre disque et provoquer des problèmes. D'un autre côté, si les indices sont si mauvais, cela aiderait probablement à la fin plus qu'il ne nuit.
Outre ces deux raisons, il peut encore y avoir un troisième problème
Il se peut que votre serveur soit configuré probablement, vous n'avez changé aucun code dans ce temps, juste ajouté quelques lignes. Toutes les statistiques sont mises à jour et tous les caches sont reconstruits. Tous vos indices sont réorganisés comme vous en avez besoin, mais toujours - rien ne fonctionne. Il se peut que vous ayez atteint la limite de mémoire disponible dans vos processus. Vous en avez peut-être besoin de plus. Vous pouvez simplement vérifier s'il existe un processus qui tente d'obtenir plus de mémoire que vous n'en avez.
Vous pouvez vérifier cela en utilisant cette commande:
SELECT * FROM sys.dm_exec_query_memory_grants
Il vous fournira une liste de toutes les sessions qui consomment de la mémoire. Il peut y avoir une requête qui attend toujours d’obtenir de la mémoire. Ces requêtes peuvent être facilement filtrées. Toutes les sessions où granted_memory_kb IS NULL
. Ce sont des sessions qui demandaient de la mémoire mais ne l'obtiennent pas. Une autre chose peut être une mémoire accordée qui peut être trop faible. Vous pouvez comparer les colonnes requested_memory_kb
avec granted_memory_kb
. Required indique la quantité de mémoire dont le processus a besoin pour fonctionner de manière optimale, tandis que grant affiche la mémoire qui est activée pour le processus. Si un processus a besoin de 2 Go pour s'exécuter mais n'obtient que 2 Mo ... vous pouvez l'obtenir par vous-même. ;-)
Une autre façon consiste à vérifier RESSOURCE_SEMAPHORE
:
SELECT * FROM sys.dm_exec_query_resource_semaphore
Vous pouvez jeter un œil aux waiter_count
et grantee_count
. Si le serveur est au-dessus de 0, vous avez une pression sur votre mémoire, ce qui peut provoquer un échange et provoquer la pression du disque que vous voyez dans le perfmon.