Je gère actuellement un cluster de serveurs pour un système SaaS. Nous avons actuellement 6 serveurs SQL exécutant MSSQL 2008 R2. Chaque serveur est une machine virtuelle quad core avec 16 Go de RAM provisionné sur un rack de serveurs. Nous remplissons chaque serveur avec un maximum de 50 instances autorisées par SQL Server. Chaque instance sera accédée sporadiquement par un maximum de 10 clients simultanément, et chaque base de données ne sera généralement qu'environ 100 Mo à 500 Mo en taille.
Actuellement, chaque instance a été installée sans définir de limites de mémoire, mais ce que nous avons constaté, c'est que les premières instances ont tendance à utiliser trop de mémoire, laissant les instances ultérieures (dans l'ordre de démarrage) avec à peine 200 Mo de travail et le système d'exploitation du serveur avec moins de 1% de mémoire physique disponible. Cela semble provoquer un échange de disque excessif et des problèmes de latence.
Quelle est la méthode recommandée pour diviser l'allocation de mémoire dans ce cas? Existe-t-il une formule pour déterminer approximativement la quantité de mémoire dont une instance a besoin au minimum à partir du nombre de clients et de la taille de la base de données? Puis-je définir un maximum de 300 Mo par instance et en finir avec cela?
J'ai finalement compris comment configurer tout où cela semble très stable et est complètement symétrique dans toutes les instances, et comme il a fallu creuser et faire, j'ai pensé que je devrais partager la solution à laquelle je suis arrivé. Ce n'est probablement pas pour tout le monde, mais cela semble être la meilleure solution pour moi.
La clé se trouve dans cette API: https://docs.Microsoft.com/en-us/windows/desktop/api/memoryapi/nf-memoryapi-setprocessworkingsetsizeex
Cela vous permet de définir une limite stricte sur la taille minimale et maximale du jeu de travail par processus. Cela semble être le plus propre pour moi, car cela me permet de dire au serveur SQL d'utiliser autant de mémoire qu'il le souhaite DANS cette taille de jeu, et il semble s'optimiser de manière adéquate au lieu de fonctionner à pleine capacité et d'essayer de monopoliser plus de mémoire tout le temps. Chaque instance sera permutée plus globalement, mais comme l'utilisation est sporadique pour chaque instance, cela semble fonctionner très bien, et si cela devient un problème, je peux provisionner quelques partitions de swap sur un SSD dans le rack du serveur comme espace de swap pour chaque serveur . J'ai défini la taille du jeu de travail à 300 Mo pour chaque instance via un script PowerShell lors du lancement de chaque instance, et le système d'exploitation minimal a toujours 1 Go avec lequel travailler, et tout le monde semble assez content.
Chaque serveur est une machine virtuelle quad core avec 16 Go de RAM provisionnée sur un rack de serveur.
Nous remplissons chaque serveur avec un maximum de 50 instances autorisées par SQL Server. Chaque instance sera accédée sporadiquement par un maximum de 10 clients simultanément et chaque base de données ne sera en général que d'environ 100 Mo à 500 Mo.
À mon humble avis, votre total RAM est trop faible. Veuillez lire ma réponse (avec les liens pertinents)configuration de la mémoire maximale et minimale de SQL Server . Ils changent lorsque vous avez plusieurs instances de serveur SQL exécutées sur un hôte donné.
Le plafonnement de la mémoire maximale du serveur SQL sur un serveur multi-instances est un acte d'équilibrage et la mémoire maximale ne s'applique qu'au pool de tampons. Si le serveur sql a besoin de plus de mémoire, il va l'utiliser .
Vous pouvez même utiliser Verrouiller les pages en mémoire (J'opterais toujours pour plus de mémoire avant d'activer LPM dans votre cas).
Comme point de départ,
Baseline vos instances . Cela vous aidera à évaluer ce qui est bon/acceptable pour votre charge de travail.
Utilisez le script OptimizeInstanceMemory
du blog d'Aaron pour vous aider à démarrer. Le billet de blog explique comment équilibrer dynamiquement la mémoire maximale en cas de basculement.
En remarque, vous devez surveiller l'utilisation du processeur, de la mémoire et du disque et en fonction de l'utilisation par client, vous devez également les facturer. Alternativement, vous pouvez passer à Azure :-)
Définissez un maximum de 300 Mo par instance et terminez avec. Sérieusement, vous pouvez le surveiller avec quelque chose comme ça pour déterminer quels candidats peuvent être donnés à un peu plus ou moins.
SELECT DB_NAME(database_id) AS [Database Name],
COUNT(*) * 8/1024.0 AS [Cached Size (MB)]
FROM sys.dm_os_buffer_descriptors
WHERE database_id > 4 -- system databases
AND database_id <> 32767 -- ResourceDB
GROUP BY DB_NAME(database_id)
ORDER BY [Cached Size (MB)] DESC OPTION (RECOMPILE);
À partir d'ici: tilisation de la mémoire par base de données - SQL Server
Bon article ici: http://strictlysql.blogspot.com/2013/05/how-to-size-sql-server-memory-why-is-it.html
Allouer de la mémoire au système d'exploitation (à partir de l'article):
1 GB of memory reserved to Operating System
1 GB each for every 4 GB in 4 to 16 GB
1 GB each for every 8 GB in more than 16 GB.
Répartissez le reste (c'est-à-dire 12 Go) uniformément sur les 50 bases de données, soit environ 250 Mo.
Une configuration que vous pouvez également envisager est d'activer "Optimiser pour les charges de travail ad hoc". Cela indique essentiellement au serveur SQL de ne pas mettre en cache les plans de requête complets pour les requêtes tant qu'elles n'ont pas été exécutées au moins deux fois. Cela empêchera les requêtes "ad hoc" ou à usage unique de prendre cette mémoire limitée.
En outre, vous pouvez minimiser l'impact du journal des transactions sur la mémoire en le réglant sur le mode de récupération "Simple". Vous ne pourrez le faire que si, en cas d'échec, la restauration à partir de la dernière sauvegarde est correcte. Vous pouvez lire d'autres limitations ici, https://msdn.Microsoft.com/en-us/library/ms189275.aspx .
Je pense que c'est juste jusqu'à ce que vous voyiez une raison de le changer, surtout si ce sont des clients individuels qui sont égaux à tous les autres égards.