SQL Server 2014 Sudden Slow Down / Aucune insertion / Non lié au matériel ou à l'index

8

J'exécute une 350GBbase de données sur mon PC avec environ 40 millions de lignes.

SQL Server 2014, Win7, AMD 8350 @ 4,8 GHz, 16 Go de RAM et un SSD de 500 Go (la base de données est hébergée sur son propre SSD de 500 Go, avec un débit de 500 Mo / 500 Mo en lecture / écriture).

La base de données n'est pas mise à jour, je suis juste en train de l'analyser / la lire. Avec la création de quelques-uns indexes, tout join, count(*)etc., prend moins d'une minute, ce qui est bien pour moi. J'ai exécuté quelques requêtes (après avoir exécuté une seule requête de jointure, 40 à 50 fois, cela devient lent) sur les données, et maintenant les appels qui ont duré 1 minute sont toujours en cours d'exécution 20 minutes plus tard.

Je garde un œil attentif sur les ressources système et je peux voir le SSDcoup de pied au démarrage de la requête, elle lit pendant 20-30 secondes, puis lit 121kB/secondpendant les 20 minutes suivantes. Ce n'est pas un problème de CPU ou de disque. Je suis limité avec ma quantité de RAM, mais les appels fonctionnent bien lorsque j'ai chargé la base de données pour la première fois, maintenant, rien ne fonctionne, 25 minutes plus tard.

En fait, je ne peux plus interroger la base de données, tout appel prend trop de temps, même une SELECTinstruction de base . J'ai essayé de reconstruire les index et de mettre à jour les statistiques, mais aucune différence.

Je n'ai pas beaucoup d'expérience à ce sujet, il est donc tout à fait possible que ma requête SQL soit incorrecte, auquel cas je m'attendrais à une erreur ou à la fin de l'exécution avec 0 résultats, mais aucun ne se produit.

Ce que j'essaie de faire, c'est de compter toutes les instances d'un «TypeID», dans les 5 secondes avant un temps basé sur la table ACALLS.

SELECT ACALLS.StartTime, ACALLS.Time, ACALLS.ServerIP, ACALLS.SRVR,   ACALLS.calls, ACALLS.TOKEN, COUNT(TypeID) as ExecRate
FROM ACALLS
INNER JOIN MAINVIEW ON 
MainView.TimeStamp BETWEEN ACALLS.StartTime and DATEADD(ss,-5,ACALLS.StartTime)

WHERE DATEPART(hour,MainView.TimeStamp) BETWEEN 10 and 13 and 
CAST(MainView.TimeStamp as date) = '2015-12-09' and
MainView.TypeID = '123456789'
GROUP BY Acalls.STartTime, ACALLs.TIME, ServerIp,SRVR, ACALLS.CALLS, ACALLS.TOKEN
ORDER BY Acalls.StartTime

Après avoir exécuté "Who is Running", entrez la description de l'image ici entrez la description de l'image ici


la source
Je soupçonne que cela a à voir avec les statistiques sur les tables et les types de traitement effectués pour les jointures. Vous devriez regarder les plans d'exécution des requêtes: les jointures de boucles imbriquées peuvent être un signe de problèmes.
Gordon Linoff
Avez-vous essayé AVEC RECOMPILE?
3
Publiez un plan d'exécution réel d'une requête étonnamment lente. Plus la requête est simple, mieux c'est.
usr
1
Avez-vous mis à jour les statistiques de toutes les tables? Avez-vous reconstruit tous les index? Informations sur sp_whoisactive: lien
TT.
2
Ces statistiques d'attente montrent beaucoup d'E / S, mais nous ne savons pas quelle proportion de la requête est E / S et qu'est-ce que le processeur. Effectuez les tests que j'ai recommandés pour publier les résultats.
usr

Réponses:

2

Vous avez une requête non SARGable - même si vous avez de bons index, vous ne les utilisez pas avec cette requête.

Tout d'abord, une réaction instinctive à pageiolatch_sh consiste à lire des pages du disque dans le tampon; vous n'avez pas assez de RAM pour les données qu'il essaie d'extraire.

Deuxièmement, vous devez examiner le plan d'exécution et son utilisation des index - ou leur absence.

Arrêtez d'utiliser les fonctions dans vos jointures et votre WHERE, et obtenez uniquement les données dont vous avez absolument besoin pour commencer.

  • "ENTRE ACALLS.StartTime et DATEADD (ss, -5, ACALLS.StartTime)" - débarrassez-vous de cette DATEADD dans BETWEEN.

    • S'il s'agit d'une base de données de rapports en lecture seule, créez un tableau de rapports contenant uniquement les données dont vous avez besoin, puis placez-y des index composés si nécessaire. Utilisez-la pour obtenir les clés primaires / autres clés uniques des lignes ACALLS dont vous avez besoin, puis récupérez le reste des données ACALLS plus tard.
  • OERE DATEPART (heure, MainView.TimeStamp) ENTRE 10 et 13 et CAST (MainView.TimeStamp as date) = '2015-12-09'

    • même chose - se débarrasser du CAST - changer '2015-12-09' en un ou deux @ paramètres du bon type de données pour MainView.TimeStamp> = @StartTimestamp AND MainView.TimeStamp <@EndTimestamp

    • et supprimez ce DATEPART en limitant @StartTimestamp et @EndTimestamp pour inclure également vos critères d'heures.

Peut-être charger une table #temp avec juste les clés primaires / uniques des lignes qui répondent à ces critères MainView avant la jointure.

Hmm ... aussi, si Mainview est une vue complexe, allez directement aux tables de base pour charger cette table #temp

N'oubliez pas d'utiliser Profiler pour vérifier et voir si l'ajout (composé si besoin est) d'index sur la #temp ou une autre table intermédiaire est un gain net ou une perte nette :).

Mots de passe anti-faiblesse
la source
1

créer un index composite non clusterisé sur la vue principale (typeid, horodatage).

changez votre "où" sur mainview afin de ne pas utiliser de fonction par rapport aux colonnes mainview. cela peut vous obliger à précalculer ces valeurs en tant que variables avant d'exécuter la requête si vous avez besoin qu'elles soient plus dynamiques.

WHERE MainView.TimeStamp BETWEEN '2015-12-09 10:00' and '2015-12-09 13:00'

créer un index non cluster sur ACALLS.StartTime.

changer la jointure en ACALLS pour être

WHERE ACALLS.StartTime BETWEEN DATEADD(ss,-5,MainView.TimeStamp) AND MainView.TimeStamp

d'après ma compréhension, cela gérera votre logique et se joindra à une performance assez élevée et vous éloignera de l'IO.

ma meilleure supposition quant à ce que vous rencontrez est que vos données sont vidées du cache et / ou tempdb se répand sur le disque de temps en temps, donc la meilleure solution que j'ai généralement trouvée est de mieux écrire les requêtes limiter l'utilisation de tempdb et de la mémoire et les problèmes sous-jacents disparaissent.

Bruce Dunwiddie
la source