J'ai migré un grand site Web et une base de données à partir d'un ancien serveur (Windows 2008/SQL Server 2008/16 Go RAM/2 x 2,5 GHz Quad Core/SAS ) vers un serveur plus récent et bien meilleur (Windows 2008 R2/SQL Server 2012 SP1/64 Go RAM/2 processeurs 16 Core 2,1 GHz/disques SSD).
J'ai détaché les fichiers de la base de données sur l'ancien serveur, les ai copiés et attachés sur le nouveau serveur. Tout s'est très bien passé.
Après cela, j'ai changé le niveau de compatibilité en 110, mis à jour les statistiques, reconstruit les index.
À ma grande déception, j'ai remarqué que la plupart des requêtes SQL sont beaucoup plus lentes (2-3-4 fois plus lentement) sur le nouveau serveur SQL 2012 que sur l'ancien serveur SQL 2008.
Par exemple, sur une table avec environ 700k enregistrements, sur l'ancien serveur, une requête sur l'index prenait environ 100 ms. Sur le nouveau serveur, la même requête prend environ 350 ms.
Il en va de même pour toutes les requêtes.
J'apprécierais un peu d'aide ici. Faites-moi savoir quoi vérifier/vérifier. Parce que j'ai du mal à croire que sur un meilleur serveur avec un SQL Server plus récent, les performances sont pires.
Plus de détails:
La mémoire est réglée sur max.
J'ai cette table et cet index:
CREATE TABLE [dbo].[Answer_Details_23](
[ID] [int] IDENTITY(1,1) NOT NULL,
[UserID] [int] NOT NULL,
[SurveyID] [int] NOT NULL,
[CustomerID] [int] NOT NULL default 0,
[SummaryID] [int] NOT NULL,
[QuestionID] [int] NOT NULL,
[RowID] [int] NOT NULL default 0,
[OptionID] [int] NOT NULL default 0,
[EnteredText] [ntext] NULL,
CONSTRAINT [Answer_Details_23_PK] PRIMARY KEY NONCLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
CREATE NONCLUSTERED INDEX [IDX_Answer_Details_23_SummaryID_QuestionID] ON [dbo].[Answer_Details_23]
(
[SummaryID] ASC,
[QuestionID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
J'ai exécuté cette requête:
set statistics time on;
select summaryid, count(summaryid) from Answer_Details_23 group by summaryid order by count(summaryid) desc;
set statistics time off;
OLD SERVER - Temps d'exécution SQL Server: temps CPU = 419 ms, temps écoulé = 695 ms.
NOUVEAU SERVEUR - Temps d'exécution SQL Server: temps CPU = 1340 ms, temps écoulé = 1636 ms.
PLANS D'EXÉCUTION téléchargés ici: http://we.tl/ARbPuvf9t8
Mise à jour ultérieure:
Maintenant, SQL Server Execution Times: temps CPU = 550 ms, temps écoulé = 828 ms.
C'est toujours pire que l'ancien serveur, mais pas si mal. Si vous avez d'autres suggestions (autres que des optimisations de requêtes locales), n'hésitez pas à commenter.
J'ai rencontré des problèmes similaires avec SQL Server, il est possible que votre serveur ne soit pas configuré de manière optimale. Les nouveaux Xeons sont livrés avec TurboBoost, HT, etc. qui peuvent affecter de manière significative les performances du serveur.
Par exemple, nous avons eu du succès avec; Configuration à faible latence pour les serveurs Dell
Les paramètres seront applicables aux serveurs non Dell, ils peuvent simplement avoir des noms différents.
Nous avons également amélioré les performances en définissant le profil de gestion de l'alimentation de Windows sur hautes performances, à partir de Balanced. Un dernier élément est qu'il est recommandé de réserver jusqu'à 8 Go de mémoire pour le système d'exploitation sur les serveurs x64, l'installation SQL par défaut prend toute la mémoire. Vous pouvez essayer de réserver 4/8 Go en définissant votre configuration de mémoire SQL Server maximale sur 4/8 Go de moins que la mémoire totale.
Ma recommandation serait de revenir à l'ancien serveur si possible. Si vous n'avez pas de scripts de régression/automatisation/chargement disponibles, le mieux que vous puissiez faire est d'enregistrer l'activité de votre système pendant 1 à 4 heures pendant une période d'activité élevée. Configurez ensuite un serveur Web identique à la production et une machine cliente pour exécuter le script. Exécutez la même activité sur le nouveau serveur, modifiez la configuration et réexécutez la même activité. Vraiment, vous voudriez faire beaucoup plus, mais il ne semble pas que ce serait viable et n'entre pas dans le cadre de cette question.
Faites-moi savoir quoi vérifier/vérifier
Vous avez un problème de performances. Suivez une méthodologie de dépannage des performances telle que Attentes et files d'attente pour identifier le goulot d'étranglement. La méthodologie liée vous montre quoi mesurer et comment. Postez ici les résultats et nous pouvons vous aider avec des conseils spécifiques basés sur vos mesures réelles. Comme il est trop ouvert et que personne ne peut deviner. Le limiter à un problème spécifique éliminera les conjectures.
Après la mise à jour
Les plans sont assez différents. L'ancien plan avait un agrégat de flux bas sur la pile qui a en fait une mauvaise estimation de cardinalité (141k contre 108k) et les calculs de hachage ont encore mal interprété, dans l'autre sens (35k contre 108k). Le nouveau plan n'a pas l'agrégat de flux et a des estimations précises jusqu'au sommet. Bien sûr, cela n'explique pas pourquoi l'ancien plan s'exécutait plus rapidement .
Les analyses inférieures ont un numéro de ligne légèrement différent (non significatif) mais des coûts assez différents: l'ancien est de 2,49884 (processeur IO 2,28979 0,20905) par rapport au nouveau 1,59109 (processeur IO 1,53868 0,0524084). Une fois encore, cela indiquerait une meilleure exécution en 2012 (la reconstruction de l'indice a peut-être réduit la fragmentation?).
Ce qui est très différent, c'est le nombre de threads: 32 dans les nouveaux (chacun obtenant ~ 23k lignes) contre 8 dans les anciens (chacun obtenant ~ 95k lignes). Le tableau est assez étroit. Il pourrait être que le grand nombre de threads nuit réellement aux performances en raison de beaucoup plus fréquentes invalidations du cache . Je voudrais essayer:
Vous avez remarqué votre commentaire:
Ajout du plan d'exécution avec maxdop 8 Query est en fait plus rapide de cette façon
Ce ne sont probablement que des processeurs qui marchent les uns sur les autres. Avec les SSD en place, le IO est probablement presque nul et la table est définitivement trop petite pour justifier 32 scanners. Ce swap d'échange invalide probablement L1/L2 constamment.
Pour la plupart des systèmes multicœurs modernes, et en particulier les systèmes multi-processeurs, l'architecture matérielle est telle que certaines parties de la mémoire sont éloignées de certains cœurs/processeurs, et certaines parties de la mémoire sont proches de certains cœurs/processeurs. C'est ce qu'on appelle l'architecture de mémoire non uniforme, ou NUMA pour faire court. Vous voulez que votre paramètre MAXDOP corresponde au nombre de cœurs par nœud NUMA pour minimiser le nombre de fois qu'un nœud numa donné doit sortir de sa propre mémoire pour les données.
Vous pouvez utiliser les éléments suivants pour vérifier la configuration de votre nouvelle machine et vous assurer que MAXDOP est réglé sur le meilleur paramètre, au niveau matériel:
DECLARE @CPUs int;
DECLARE @NumaNodes int;
DECLARE @ServerRAMInMB int;
SET @ServerRAMinMB = (SELECT (i.physical_memory_kb / 1024) AS ServerMemory
FROM sys.dm_os_sys_info i);
SET @CPUs = (SELECT i.cpu_count from sys.dm_os_sys_info i);
SET @NumaNodes = (SELECT MAX(c.memory_node_id) + 1 FROM sys.dm_os_memory_clerks c
WHERE memory_node_id < 64);
SELECT @ServerRamInMB, @CPUs, @NumaNodes;
IF @CPUs > 4 /* this would be 4 cores, not 4 CPUs */
BEGIN
DECLARE @MaxDOP int;
SET @MaxDOP = @CPUs * 0.75;
IF @MaxDOP > (@CPUs / @NumaNodes) SET @MaxDOP = (@CPUs / @NumaNodes);
EXEC sp_configure 'max degree of parallelism', @MaxDOP;
EXEC sp_configure 'cost threshold for parallelism', 4;
END
J'ai inclus le @ServerRamInMB
paramètre ici puisque je l'utilise pour configurer le Max Server Memory
et Min Server Memory
les options de configuration aux valeurs appropriées pour le serveur donné.
Dans quel mode d'édition et de licence êtes-vous? Vous n'utilisez probablement pas tous les cœurs. Voir la note sur cette page - http://msdn.Microsoft.com/en-us/library/ms143760.aspx
"Enterprise Edition with Server + Client Access License (CAL) based license est limitée à un maximum de 20 cœurs par instance de SQL Server."
J'ai eu le même problème que celui décrit dans cette page: la commutation des paramètres d'alimentation de "équilibré" à "haute performance" a fait une différence spectaculaire - plus que doubler les temps de réponse. Maintenant que nous utilisons des SSD, je ne pense pas que la consommation d'énergie soit le problème.