Scénario
Supposons que j'ai un serveur SQL avec 4 sockets avec chaque 1 nœud NUMA. Chaque socket possède 4 cœurs physiques. Il y a 512 Go de mémoire au total, donc chaque nœud NUMA dispose de 128 Go de RAM.
Une table de clés est chargée dans le premier nœud NUMA.
Question
Supposons que nous lisons beaucoup de trafic à partir de ce tableau. Si tous les cœurs physiques du socket propriétaire du nœud NUMA ont 100% d'utilisation du processeur, cela influence-t-il négativement le coût de l'accès NUMA non local provenant d'autres sockets? Ou d'un autre côté, le coût de l'accès NUMA non local est-il indépendant de l'occupation de ce socket?
J'espère que ma question a un sens. S'il vous plaît faites le moi savoir si ce n'est pas le cas, je vais essayer de clarifier.
Contexte
Nous avons eu un problème de base de données sur notre serveur de production la semaine dernière et certaines de nos activités traitées ont semblé plus affectées que d'autres. Nous avons eu des requêtes avec peu de lectures logiques prenant plus d'une minute. Nous avons examiné l'utilisation globale du processeur, qui était d'environ 60%. Nous n'avons pas examiné les mesures de CPU spécifiques au socket. Les mesures d'E / S étaient moyennes.
Réponses:
Une lourde question :-) Je vais décrire certains des facteurs impliqués. Dans un contexte donné, ces facteurs et d'autres peuvent varier et produire un résultat intéressant.
Désolé, je n'ai pas pu raccourcir cela beaucoup plus ...
Accumulé ms ms vs IO logique
J'utilise très souvent des graphiques d'E / S logiques (ou, dans la terminologie perfmon, des «recherches de page de pool de mémoire tampon») par rapport à l'utilisation du processeur, afin de mesurer l'efficacité du processeur des charges de travail et de rechercher des cas propices aux verrouillages.
Mais SQL Server accumule du temps CPU avec beaucoup d'activités autres que les recherches de page et les verrous tournants:
De nombreuses autres activités ralentiront considérablement le temps processeur sans être reflétées dans les recherches de page.
Dans les charges de travail que j'observe, la principale activité de tri "intensif d'E / S non logique mais engloutissant le processeur" est l'activité de tri / hachage.
Il va de soi: considérons un exemple artificiel de deux requêtes sur une table de hachage sans index non cluster. Les deux requêtes ont des jeux de résultats identiques, mais l'un des jeux de résultats est complètement non ordonné et le deuxième jeu de résultats est ordonné par plus d'une des colonnes sélectionnées. La deuxième requête devrait consommer plus de temps CPU, même si elle ferait référence au même nombre de pages dans le pool de mémoire tampon.
En savoir plus sur la mémoire de l'espace de travail et la quantité d'espace de travail octroyé qui a été utilisée, dans ces messages:
http://sql-sasquatch.blogspot.com/2015/08/sql-server-grantedreservedstolen_4.html
http://sql-sasquatch.blogspot.com/2015/08/sql-server-workspace-memory-with-twist.html
http://sql-sasquatch.blogspot.com/2015/03/resource-governor-to-restrict-max-query.html
Alignement des nœuds de mémoire logique SQL Server avec les nœuds NUMA physiques
SQL Server (depuis l'incorporation de ses stratégies prenant en charge NUMA) crée par défaut un nœud de mémoire SQLOS pour chaque nœud NUMA sur le serveur. À mesure que les allocations de mémoire augmentent, chaque allocation est contrôlée par l'un des nœuds de mémoire SQLOS.
Idéalement, les nœuds de mémoire SQLOS sont complètement alignés avec les nœuds NUMA physiques. C'est-à-dire que chaque nœud de mémoire SQLOS contient de la mémoire à partir d'un seul nœud NUMA, aucun autre nœud de mémoire SQLOS ne contenant également de mémoire à partir de ce même nœud NUMA.
Cependant, cette situation idéale n'est pas toujours le cas.
Le billet de blog CSS SQL Server Engineers suivant (également inclus dans la réponse de Kin) détaille le comportement qui peut conduire à la persistance d'allocations de mémoire de nœuds croisés NUMA pour les nœuds de mémoire SQLOS. Lorsque cela se produit, l'impact sur les performances peut être dévastateur.
Il y a eu quelques correctifs pour le cas particulièrement douloureux de référence de nœud croisé NUMA persistante. Probablement d'autres en plus de ces deux:
CORRECTIF: des problèmes de performances se produisent dans les environnements NUMA lors du traitement des pages étrangères dans SQL Server 2012 ou SQL Server 2014
CORRECTIF: problèmes de performances de SQL Server dans les environnements NUMA
Conflit Spinlock lors de l'allocation de la mémoire de l'espace de travail
C'est là que ça commence à s'amuser. J'ai déjà décrit que le travail de tri et de hachage dans la mémoire de l'espace de travail consomme du processeur mais n'est pas reflété dans les numéros de recherche de bpool.
La contention de Spinlock est une autre couche à ce plaisir particulier. Lorsque la mémoire est volée du pool de tampons et allouée pour être utilisée contre une allocation de mémoire de requête, l'accès à la mémoire est sérialisé avec un verrou tournant. Par défaut, cela se produit avec une ressource partitionnée au niveau du nœud NUMA. Ainsi, chaque requête sur le même noeud NUMA utilisant la mémoire de l'espace de travail peut potentiellement rencontrer des conflits de verrou tournant lors du vol de mémoire contre des octrois. Très important à noter: ce n'est pas un risque de contention "une fois par requête", comme ce serait le cas si le point de contestation était au moment de l'octroi réel. Au contraire, son quand la mémoire est volée contre la subvention - donc une requête avec une très grande allocation de mémoire aura de nombreuses possibilités de contention de verrou tournant si elle utilise la majeure partie de sa subvention.
L'indicateur de trace 8048 fait un excellent travail pour soulager cette contention en partitionnant davantage la ressource au niveau principal.
Microsoft dit "considérez l'indicateur de trace 8048 si 8 cœurs ou plus par socket". Mais ... ce n'est pas vraiment le nombre de cœurs par socket (tant qu'il y en a plusieurs), mais plutôt le nombre d'opportunités de contention dans le travail effectué sur un seul nœud NUMA.
Sur les processeurs AMD collés (12 cœurs par socket, 2 nœuds NUMA par socket), il y avait 6 cœurs par nœud NUMA. J'ai vu un système avec 4 de ces processeurs (donc huit nœuds NUMA, 6 cœurs chacun) qui était coincé dans le convoi spinlock jusqu'à ce que l'indicateur de trace 8048 soit activé.
J'ai vu cette contention de verrou tournant ralentir les performances sur des machines virtuelles aussi petites que 4 vCPU. L'indicateur de trace 8048 a fait ce qu'il était censé faire lorsqu'il était activé sur ces systèmes.
Étant donné qu'il existe encore des processeurs optimisés en fréquence de 4 cœurs, avec la bonne charge de travail, ils bénéficieraient également de l'indicateur de trace 8048.
CMEMTHREAD attend accompagne le type de conflit de verrou tournant que l'indicateur de trace 8048 soulage. Mais une mise en garde: les attentes CMEMTHREAD sont un symptôme corroborant, et non la cause première de ce problème particulier. J'ai vu des systèmes avec un "temps d'attente" CMEMTHREAD élevé où l'indicateur de trace 8048 et / ou 9024 a été retardé dans le déploiement car le temps d'attente CMEMTHREAD cumulé était assez faible. Avec les verrous tournants, le temps d'attente accumulé n'est généralement pas la bonne chose à regarder. Au contraire, vous voulez regarder le temps CPU perdu - représenté principalement par les spins eux-mêmes, secondairement par les attentes associées qui représentent des changements de contexte potentiellement inutiles.
Affectation de tâches aux planificateurs
Sur les systèmes NUMA, les connexions sont distribuées aux nœuds NUMA (enfin - en fait aux groupes d'ordonnanceurs SQLOS qui leur sont associés) round-robin, en supposant qu'il n'y a pas de points de terminaison de connexion associés à des nœuds NUMA particuliers. Si une session exécute une requête parallèle, il existe une forte préférence pour utiliser des travailleurs à partir d'un seul nœud NUMA. Hmmm ... considérons un serveur à 4 nœuds NUMA avec une requête complexe divisée en 4 chemins, et par défaut 0 MAXDOP. Même si la requête n'utilisait que des threads de travail MAXDOP, il y aurait 4 threads de travail pour chaque CPU logique sur le nœud NUMA. Mais il y a 4 chemins dans le plan complexe - donc chaque CPU logique sur le nœud NUMA pourrait avoir 16 travailleurs dessus - le tout pour une seule requête!
C'est pourquoi parfois vous verrez un nœud NUMA travailler dur tandis que d'autres flânent.
Il y a quelques autres nuances dans l'attribution des tâches. Mais le principal point à retenir est que le CPU occupé ne sera pas nécessairement réparti également entre les nœuds NUMA. (Il est également bon de se rendre compte que les insertions de pages bpool (lectures ou écritures de première page) iront dans le bpool dans le nœud de mémoire SQLOS associé au planificateur sur lequel se trouve le travailleur. Et les pages volées proviendront préférentiellement de la mémoire SQLOS "locale" nœud, aussi.
J'ai trouvé qu'apporter maxdop de 0 à pas plus de 8 est utile. En fonction du profil de charge de travail (principalement imo sur le nombre de requêtes simultanées potentiellement de longue durée attendues), le passage à MAXDOP = 2 peut être justifié.
L'ajustement du seuil de coût du parallélisme peut également être utile. Les systèmes sur lesquels je travaille ont tendance à être consommés avec des requêtes à coût élevé et rencontrent rarement un plan inférieur à 50 ou 100, j'ai donc eu plus de traction en ajustant maxdop (oten au niveau du groupe de charge de travail) qu'en ajustant le seuil de coût.
SQL Server PLE avec 8 nœuds NUMA
Dans cet article, une combinaison de conflits de verrous tournants autour de la mémoire de l'espace de travail et d'une répartition inégale des tâches est discutée. Voyez - ces choses tissent vraiment ensemble :-)
40 requêtes parallèles simultanées SQL Server + (2 sockets * 10 cœurs par socket) = convoi spinlock
Placement de données pertinent dans le pool
C'est la condition qui, à mon avis, est la plus intuitive lorsqu'il s'agit de serveurs NUMA. Il est également, le plus souvent, peu important pour les performances de la charge de travail.
Que se passe-t-il si la table est lue dans le pool sur le nœud NUMA 3, et qu'une requête sur le nœud NUMA 4 analyse ensuite la table en effectuant toutes les recherches de pool sur les nœuds NUMA?
Linchi Shea a un excellent article sur cet impact sur les performances:
L'accès à la mémoire sur les nœuds NUMA entraîne une petite latence de mémoire supplémentaire. Je suis sûr que certaines charges de travail doivent éliminer cette latence de mémoire de base supplémentaire pour des performances optimales - ce n'est pas un problème sur les systèmes avec lesquels je travaille.
Mais - l'accès entre les nœuds apporte également un autre point de transfert qui peut potentiellement saturer. S'il y a tellement d'activité que la bande passante mémoire entre les nœuds NUMA est saturée, la latence de la mémoire entre les nœuds augmentera. Le même travail nécessitera des cycles CPU supplémentaires.
Encore une fois - je suis sûr qu'il existe des charges de travail telles que la bande passante mémoire est un facteur critique. Pour mes systèmes, cependant, les autres considérations que j'énumère sont plus importantes.
Placement de la mémoire physique
Celui-ci est rare mais quand ça compte, ça compte vraiment. Sur la plupart des serveurs, l'installation de la mémoire va presque naturellement s'équilibrer entre les nœuds NUMA. Mais dans certains cas, une attention particulière est nécessaire pour équilibrer la mémoire entre les nœuds. Les performances de certains systèmes peuvent être complètement saccagées si la mémoire a été insérée de manière à ne pas être équilibrée. Il s'agit cependant de le régler et de l'oublier. Assez rare de découvrir un problème comme celui-ci après des mois de service de production par opposition à après la première journée vraiment chargée :-)
LA GRANDE FINITION!
Quelqu'un d'autre a fait valoir qu'un mauvais choix de plan, peut-être en raison de statistiques obsolètes, pourrait entraîner les symptômes que vous avez vus. Cela n'a pas été le cas dans mon expérience. Des plans médiocres peuvent facilement faire en sorte qu'une requête prenne plus de temps que prévu, mais généralement parce que des E / S plus logiques que nécessaire sont effectuées. Ou en raison d'un déversement sur tempdb. Un déversement massif vers tempdb doit être évident lors de l'observation du serveur - et plutôt que d'un CPU élevé, on peut s'attendre à un temps d'attente mesurable pour les écritures de disque liées au déversement.
Au lieu de cela, si la situation que vous avez observée est liée à NUMA, je m'attends à ce que ce soit une combinaison des facteurs énumérés ci-dessus, principalement:
utilisation de la mémoire de l'espace de travail (qui n'apparaîtra pas dans les nombres d'E / S logiques)
qui peut être un noeud cross-NUMA en raison de conditions persistantes de mémoire étrangère (si tel est le cas, recherchez les correctifs appropriés)
et qui peut entraîner une contention de verrou tournant dans le nœud NUMA chaque fois qu'une allocation est effectuée contre une attribution (correction avec T8048)
et peut être effectué par des travailleurs sur des processeurs logiques surchargés par d'autres travailleurs de requêtes parallèles (ajustez maxdop et / ou le seuil de coût du parallélisme si nécessaire)
la source
( veuillez mettre à jour votre question avec la
coreinfo -v
sortie (d'un utilitaire sysinternal) pour obtenir un meilleur contexte de votre CPU / sockets et de la distribution NUMA )Il me semble que vous aboyez au mauvais arbre. SQL Server est au
NUMA
courant. Il y a une pénalité de performance beaucoup plus faible pour effectuer un accès croisé à la mémoire NUMA . Vous pouvez également utiliser cette requête pour voir combien deNUMA
nœuds vous avez et quels CPU et cœurs sont affectés à quelsNUMA
:Ou juste combien
NUMA
:Cela se produit normalement lorsque vous avez généré de mauvais plans de requête en raison de statistiques obsolètes. Assurez-vous que vos statistiques sont mises à jour et que vos index sont correctement défragmentés .
En outre, vous devez définir MAXDOP sur une valeur plus sensible pour éviter la famine du thread de travail .
Définissez votre
cost threshold of parallelism
valeur par défaut de 5 à une bonne valeur de départ comme 45, puis surveillez cette valeur et ajustez-la en fonction de votre environnement.Si vous exécutez un grand nombre de requêtes ad hoc, activez (défini sur 1)
optimize for ad hoc workloads
pour éviter le gonflement du cache du plan.À utiliser avec prudence: vous pouvez utiliser T8048 si vous exécutez SQL Server 2008/2008 R2 sur des machines plus récentes avec plus de 8 processeurs présentés par nœud NUMA et il existe un correctif si vous utilisez SQL Server 2012 ou 2014 .
Je vous recommande vivement de commencer à collecter des informations sur les statistiques d'attente sur votre instance de serveur de base de données.
Référez-vous à: Comment ça marche: SQL Server (NUMA Local, Foreign and Away Memory Blocks)
la source
Du point de vue purement matériel, la gestion de la mémoire principale de l'architecture Nehalem est gérée par un contrôleur de mémoire intégré, c'est la partie "Un-core" de la puce CPU qui est séparée de la partie sur laquelle les cœurs réels vivent, comme la mémoire est effectivement `` câblée '' à chaque CPU, l'accès à la mémoire étrangère AFAIK se fait via l'interconnexion de chemin rapide (à partir de Nehalem), je dirais donc que la saturation du cœur du CPU sur un nœud NUMA local ne devrait pas affecter l'accès à distance à cette mémoire.
Vous pourriez trouver ce lien utile:
http://cs.nyu.edu/~lerner/spring10/projects/NUMA.pdf
Chris
la source