Augmentation de la RAM, pire performance

9

Installer:

  • Windows Server 2008 R2
  • SQL Server 2008 R2 SP1
  • 240 Go de RAM
  • TempDB est 8 x 16 Go de fichiers de données sans croissance automatique (128 Go au total)
  • Serveur physique / autonome

Ce serveur est utilisé pour le traitement ETL. Nous venons d'installer plus de RAM sur ce serveur pour un total de 240 Go de RAM. Les services SQL Server sont les seules choses réellement en cours d'exécution.

La mémoire apparaît très bien dans le BIOS, OpenManage et Windows.

Si je configure SQL Server pour utiliser une mémoire Min / Max de 70 / 100GB, nous n'avons aucun problème. Cependant, une fois que j'ai augmenté cela à 120/150 Go, j'obtiens l'erreur suivante lorsque j'exécute l'un de nos processus ETL:

Impossible d'allouer de l'espace pour l'objet '<objet système temporaire: 422234507706368>' dans la base de données 'tempdb' car le groupe de fichiers 'PRIMARY' est plein. Créez de l'espace disque en supprimant les fichiers inutiles, en supprimant des objets dans le groupe de fichiers, en ajoutant des fichiers supplémentaires au groupe de fichiers ou en activant la croissance automatique pour les fichiers existants dans le groupe de fichiers. (Msg 1105, état 2, procédure inconnue, ligne 1)

Nous n'avons jamais rencontré ce problème avant de modifier la configuration de la mémoire. Après avoir reconfiguré à nouveau le 70 / 100GB d'origine, nous ne recevons pas cette erreur.

Ce que j'ai essayé:

  1. Définissez les fichiers de données TempDB pour une croissance automatique. Cela entraîne simplement la croissance automatique des fichiers jusqu'à ce que la capacité du disque soit atteinte, puis échoue.
  2. Ajoutez d'autres fichiers de données TempDB. Même erreur que celle illustrée.
  3. Augmentez la taille TempDB à 8x32 Go (256 Go au total)

Je ne sais pas ce qui pourrait causer ce problème.

Derek Kromm
la source
2
Votre mémoire est-elle équilibrée entre les nœuds NUMA? Et vos processeurs? Le journal SQL Server indique-t-il le nombre de processeurs en cours d'utilisation au démarrage?
Aaron Bertrand
1
Qu'utilisez-vous pour les processus ETL? SSIS ou un outil similaire? S'il s'agit d'un outil en dehors de SQL Server, l'exécutez-vous sur le même serveur que votre instance SQL Server?
Mike Fal
1
C'est un bon point @Mike, si le processus ETL ne parvient pas à récupérer suffisamment de mémoire pour faire son travail, car SQL Server en utilise trop, il devra peut-être pousser le travail vers tempdb.
Aaron Bertrand
1
Voici un bon début pour surveiller l'utilisation de tempdb: msdn.microsoft.com/en-us/library/ms176029(v=SQL.105).aspx . Cela devrait vous donner une idée de ce qui se passe.
Thomas Stringer
2
Avez-vous fait une analyse de ce qui fonctionne réellement lorsque vous êtes en train de développer TempDB? Un simple sp_who2 / sp_whoisactive? Il me semble que vous avez des transactions de longue durée qui pourraient être mieux gérées, mais difficiles à dire. Personnellement, je ne m'attacherais pas au changement de mémoire, mais regardez d'abord le code et voyez si cela fonctionne correctement.
Mike Fal

Réponses:

3

Merci à tous pour votre aide.

Après avoir parcouru certains plans d'exécution, il s'avère qu'il existe un JOIN qui est traité différemment en fonction de la quantité de RAM disponible. Avec moins de RAM, il l'évalue avec un Hash; avec plus de RAM, il utilise une série de jointures de fusion.

Donc, fondamentalement, cela se résumait à un T-SQL mal écrit, que je refactorise actuellement.

Derek Kromm
la source
4
C'est assez contre-intuitif car une jointure de hachage nécessite une allocation de mémoire alors que la fusion ne le fait pas. Existe-t-il une opération de tri supplémentaire pour prendre en charge la jointure de fusion?
Martin Smith
1

Ce n'est pas une réponse à la question, juste un code que je ne voulais pas publier dans un commentaire. Pour voir l'équilibre de vos planificateurs et de la mémoire sur les nœuds NUMA (et également pour voir si des nœuds ne sont pas visibles en ligne):

SELECT 
  parent_node_id, 
  [status],
  AVG(current_tasks_count) AS avg_tasks_count, 
  AVG(load_factor) AS avg_load_factor,
  scheduler_count = COUNT(*)
FROM sys.dm_os_schedulers
GROUP BY parent_node_id, [status];

SELECT 
  memory_node_id, 
  name, 
  SUM(single_pages_kb + multi_pages_kb) AS memory_kb
FROM sys.dm_os_memory_clerks
GROUP BY memory_node_id, name;

(Dans SQL Server 2012, le dernier SUMdevrait être SUM(pages_kb)car il n'y a plus d'allocateurs séparés d'une page et de plusieurs pages.)

Aaron Bertrand
la source