J'ai une longue requête en cours d'exécution (table de fait avec 100 millions de lignes rejoignant un certain nombre de petites tables sombres puis groupe par) qui répandit à TEMPDB, même si (après quelque résled), le CE est très proche du nombre réel de lignes, voir plan :
À la recherche d'une explication, j'ai remarqué l'info de la subvention de la mémoire suivante:
Environnement: SQL Server 2012 SP1 Enterprise, Server RAM 256 Go, SQL Server Memory Max Memory 200 Go, tampon Taille de la piscine 42 Go, Espace de travail Max taille max 156 gb (accordéMemory = 156 * 25% ~ = 38 Gb)
Plan de requête anonyme à coller le plan
Lorsque vous forcez un agrégat de match de hachage (au lieu d'un agrégat de type + de flux), la requête terrait toujours 3 à 4 fois plus rapidement. Malheureusement, la requête vient de Cognos et nous n'avons aucun moyen de le changer.
Il n'y a pas de déversement de hachage dans le plan d'agrégats de hachage. L'optimiseur de requêtes ne choisira pas l'agrégat de match de hasch car si je regarde le coût de l'opérateur pour l'agrégat de flux Hash VS, le coût de la CPU du groupe HASH est de 2 à 3 fois plus élevé que de faire l'agrégat de flux.
Dans les groupes de flux et de hachage, les lignes de sortie estimées sont exactement identiques à celles de l'entrée (environ 100 millions de rangées).
La requête utilise un seul index de colonne NC et les statistiques de colonne sont toutes régulièrement mises à jour.
- cela signifie-t-il peu importe la qualité de la CE, la requête n'a aucune chance de ne pas renverser? puisque la requête Max Ram est durcie à 38 Go
La subvention globale de la mémoire pour votre requête semble plafonnée à 37 Go donnée à votre configuration actuelle du matériel et du serveur SQL.
Si le tri ne peut pas être effectué dans la fraction de mémoire (0.860743 dans ce plan) de la subvention de la mémoire de requête, il se répandra à TEMPDB . Notez également que cette trieuse parallèle scinder sa fraction de la mémoire de la requête subventionner de manière égale à 12 threads, et cette allocation ne peut être rééquilibrée au moment de l'exécution.
- l'optimiseur de requêtes ne prend-elle pas en compte Max Requête Ram lors de la construction du plan? (Forcer un agrégat de match de hachage éliminerait l'étape de tri et améliorerait considérablement la performance de la requête, malheureusement, la requête réelle vient de Cognos et nous n'en avons aucun contrôle)
Oui, cela fait, mais seulement comme une contribution au cadre général du coût. L'optimiseur choisit le plan qui semble le moins cher selon son modèle. Si les chiffres sont faux, le choix du plan n'est pas susceptible d'être optimal.
Dans votre cas, le nombre réel de lignes produites par l'agrégat de flux est nettement inférieur à l'estimation:
L'optimiseur favorise l'agrégat de hachage lorsque moins de groupes plus grands sont attendus (puisque chaque groupe occupe une fente dans la table de hachage). La désinformation à propos de la densité conduit à un choix incorrect de TRY + STREAM.
Le meilleur plan serait probablement une jointure de hachage au lieu des boucles imbriquées rejoindre et un agrégat de hachage. Cela devrait pouvoir prolonger le traitement du mode de lot à l'étape d'agrégation importante.
SQL Server 2012 était assez limité dans ses transitions entre la ligne et le mode de lot. Le moteur d'exécution ne revient jamais au mode batch une fois que le traitement du mode de ligne a commencé (SO Row-Batch-Row est OK, mais le lot de lot-rangée n'est pas).
- augmentera le capuchon de 25% pour près de 100% d'une option sensible ici? (En supposant que ledit accès au serveur puisse être contrôlé pour limiter le nombre de demandes de requête simultanées)
Si vous souhaitez augmenter la quantité de mémoire disponible pour cette requête, vous pouvez certainement le faire en modifiant votre configuration de votre gouverneur de ressources. Augmentez la limite de degrés pour voir si vous pouvez localiser un bon compromis. Je me méfierais d'aller trop près de 100%.
Si la requête convient à un guide de plan, essayez un HASH GROUP
indice.
À plus long terme, la mise à niveau vers SQL Server 2016 paiera des dividendes car plus d'opérateurs peuvent exécuter en mode batch (y compris le tri), des augmentations de subventions de la mémoire dynamique sont possibles et ... environ mille autres améliorations du traitement du mode Columnstore/Batch en général.
Je peux participer partiellement à vos questions.
1) Je ne suis pas sûr de comprendre exactement votre question. Ce n'est pas vrai que SQL Server ne se répandra que sur TEMPDB, car une estimation de cardinalité est fausse. Parfois, SQL Server s'attend à ce qu'un bon plan suffisamment soigneusement se répandit à TEMPDB.
2) L'optimiseur de requête prend en compte la mémoire sur le serveur lors de la construction du plan. Un exercice utile peut être de modifier la quantité de mémoire disponible sur votre requête pour voir comment le plan de requête change. Vous pouvez le faire en modifiant les paramètres de mémoire sur le serveur, à l'aide de la gouverneur de ressources ou de la commande non documenté optimiseur DBCC What_if () . What_if est utile si vous voulez voir à quoi ressemble le plan de requête avec plus de mémoire que 200 gb.
Comme vous l'avez souligné, l'optimiseur de requêtes n'utilise pas d'agrégation de match de hasch car elle pense que le coût de la CPU de cet opérateur sera beaucoup plus élevé que le tri. L'un des critères qui rend un agrégat de match de hash attrayant pour l'optimiseur est lorsque SQL Server estime qu'il n'y aura pas de nombreuses lignes distinctes retournées. Pour votre requête SQL Server pense qu'il n'éliminera pas de lignes avec le groupe par.
Quelle est la fermeture des coûts estimés pour les plans et comment modifient-ils lorsque vous modifiez la mémoire disponible sur la requête?
3) Je ne sais pas, mais c'est certainement quelque chose que vous devriez tester soigneusement. Les options plus sûres seraient d'augmenter SQL Server Max RAM (200 semblent un peu bas, mais il existe peut-être d'autres applications installées sur le serveur ou ceci dépassent votre contrôle) ou pour améliorer les performances TEMPDB. Je peux penser à quelques autres idées d'amélioration des performances, mais toutes sont des berfatures.
Essayez d'exécuter une requête plus simple qui fait simplement un groupe sur la table de fait. Y a-t-il un moyen d'obtenir une meilleure estimation pour le nombre de valeurs distinctes? Pourrait créer des statistiques multi-colonnes aident?
Si vous ne pouvez pas modifier la requête, vous pouvez essayer de remplacer la table référencée par une vue qui sélectionne les données dont vous avez besoin, mais de manière à modifier le plan. Cela peut aider dans certains cas, mais je ne peux pas penser à un moyen d'appliquer la technique ici.
On dirait que vous avez un bon contrôle sur ce serveur afin que vous puissiez essayer créer un guide de plan . Je n'ai jamais fait cela et je n'ai jamais entendu parler de personne de dire quelque chose de positif sur les guides de planification.