SQL Server 2012 plus lent que 2008

15

J'ai migré un grand site Web et une base de données depuis un serveur plus ancien (Windows 2008 / SQL Server 2008/16 Go de RAM / 2 disques Quad Core / SAS à 2,5 GHz) vers un serveur plus récent et bien meilleur (Windows 2008 R2 / SQL Server 2012 SP1 / 64 Go de RAM / 2 processeurs 16 cœurs 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:

  • Les processeurs AMD Opteron 16 cœurs à 2,1 GHz sont bien pires que les processeurs à quatre cœurs Intel 2,5 GHz
  • Grande amélioration en changeant les options d'alimentation des fenêtres de équilibrée à haute puissance
  • Amélioration supplémentaire faisant passer le degré de parallélisme maximal à 8 et le seuil de coût à 4

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.

prog_sr08
la source
Les commentaires ne sont pas pour une discussion approfondie; cette conversation a été déplacée vers le chat .
Paul White 9

Réponses:

8

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 réussi 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.

AceCTO
la source
La charge n'est pas si élevée sur le serveur. SQL Server se trouve généralement dans 20 à 35 Go de mémoire. À tout moment, nous avions plus de 16 Go de mémoire libre. De plus, le processeur ne transmet généralement pas 10 à 15% d'utilisation.
prog_sr08
2
Jusqu'à présent, la plus grande amélioration a été obtenue en définissant la gestion de l'alimentation de Windows de équilibrée à haute puissance. Cela ressemble donc vraiment à un problème de processeur. Temps d'exécution SQL Server: temps CPU = 892 ms, temps écoulé = 874 ms.
prog_sr08
8

Faites-moi savoir quoi vérifier / vérifier

Vous avez un problème de performances. Suivez une méthodologie de dépannage des performances comme les attentes et les 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 tout en haut. 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 se peut que le grand nombre de threads nuit réellement aux performances en raison d' invalidations du cache beaucoup plus fréquentes . Je voudrais essayer:

  1. éliminer HyperThreading dans la nouvelle configuration du serveur (le cas échéant) et / ou
  2. essayez la requête avec un DOP 8.

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, l'IO est probablement à peu près nul et la table est définitivement trop petite pour justifier 32 scanners. Ce swap d'échange invalide probablement constamment L1 / L2.

Remus Rusanu
la source
1
Tout est beaucoup plus lent en 2012 qu'en 2008. Je n'essaie pas d'optimiser les requêtes ici. Je serais heureux d'avoir au moins les mêmes performances avec exactement la même base de données sur ce nouveau serveur.
prog_sr08
1
Les attentes et les files d'attente ne consistent pas à optimiser les requêtes. Il s'agit d'identifier les goulots d'étranglement.
Remus Rusanu du
J'ai téléchargé le document. Semble très intéressant. J'y suis en ce moment, mais on dirait que ça va me prendre un peu de temps. Pouvez-vous suggérer où chercher en premier?
prog_sr08
1
attendre les statistiques . réinitialisez-les sur 2008 et 2012, exécutez la charge pendant 5-10 minutes sur les deux, puis comparez les différences entre 2008 et 2012.
Remus Rusanu
J'ai peur de ne pas pouvoir comparer les statistiques entre les 2 serveurs maintenant, car le nouveau serveur héberge un site / base de données en direct. Sur l'ancien serveur est restée la base de données qui n'est plus en charge.
prog_sr08
3

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, sur le plan 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 @ServerRamInMBparamètre ici car je l'utilise pour installer les options de configuration Max Server Memoryet Min Server Memorysur des valeurs appropriées pour le serveur donné.

Max Vernon
la source
1
J'ai 64 Go de RAM, 32 cœurs de processeur, 4 nœuds numa. J'ai défini le degré maximal de parallélisme à 8 et le seuil de coût à 4. Avec ce paramètre et avec l'option d'alimentation définie sur haute puissance, SQL Server Execution Times: temps CPU = 550 ms, temps écoulé = 828 ms.
prog_sr08
C'est donc une victoire, alors? Heureux de voir que cela fonctionne pour vous!
Max Vernon
0

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

"Les licences Enterprise Edition avec Server + Client Access License (CAL) sont limitées à un maximum de 20 cœurs par instance SQL Server."

Jeff Sacksteder
la source
2
Cela ne s'appliquerait que s'il avait CAL avant et bénéficiait de droits acquis. Toujours avec seulement 20 cœurs, les performances ne devraient pas chuter sensiblement par rapport à l'ancien système (qui n'en avait que 8).
Aaron Bertrand
J'ai l'édition Web (limitée au moindre de 4 sockets ou 16 cœurs). Sur l'ancien serveur, je n'avais de toute façon que 8 cœurs.
prog_sr08
0

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.

à M
la source
-2

J'ai également parcouru ce problème pendant au moins 2 semaines sans aucune résolution robuste plutôt que de confondre un problème avec l'autre.

Enfin la résolution comme suit: -

  1. J'ai réinitialisé la compatibilité de 010 à 011

  2. Réinitialisez également la compatibilité de la base de données principale. Par défaut, sql conservera l'ancien paramètre de compatibilité. Que nous devons changer manuellement.

Bonne chance

Pramod Kumar PC
la source