J'exécute une 350GB
base 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 SSD
coup de pied au démarrage de la requête, elle lit pendant 20-30 secondes, puis lit 121kB/second
pendant 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 SELECT
instruction 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
sp_whoisactive
: lienRéponses:
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.
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 :).
la source
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.
créer un index non cluster sur ACALLS.StartTime.
changer la jointure en ACALLS pour être
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.
la source