Etienne ZINZINDOHOUE
Billets-Articles
Etrange pour une analyse de perf...
Il y a une liste des principaux compteurs a verifier...
http://www.sql-server-performance.co...eneral_p1.aspx
Au début ? C'est à dire ?Au début la taille des backup étaient autour de 5-6 Go
Et aujourd'hui on est autour de 17 Go .
Emmanuel T.
+1.
Par contre je suis un peu sceptique sur la définition de TPD dans MSDN. Une info de Bob Ward du support sur le sujet: "An EX latch prevents writers and readers. For torn-page protection, the engine must actually modify contents of the page because we place a 2-bit signature at every 512 bytes on the page. While we are doing this, we don’t want anyone to write or read the page. If you are using checksum though, we only have to change a specific field in the header. No problem to let someone read the page, but we don’t want someone else to write it." Donc la signature va dans la page elle-même, pas dans l'entête ? A suivre.
David B.
Bon désolé je scouate
Si le passage à FORCED ne change rien, je pense qu'il est plus sage de revenir à SIMPLE. C'est assez chaud de laisser sur FORCED parce que l'optimiseur peut forcer la réutilisation d'un plan complètement inadapté. Il faut être bien certain que la distribution des valeurs dans les colonnes servant d'arguments de recherche soit uniforme, et ce n'est pas toujours le cas.
David B.
Les DMVs m'ont donné suffisamment d'infos sur les perf...
Dans mon cas le problème est au niveau de la consommation CPU
C'est ce qui explique les compteurs que j'ai sélectionné, histoire de les mettre en perspective avec le traces Profiler. C'est ce qui justifie le choix de ces compteurs de perf.
A+
Etienne ZINZINDOHOUE
Billets-Articles
Etienne ZINZINDOHOUE
Billets-Articles
Etienne ZINZINDOHOUE
Billets-Articles
Oui, mais c'était quand ce début ? Il y a une semaine ? un an ? a quelle epoque ton backup ne faisait que 5/6 gb ?Au début = Lorsqu'il n'y avait pas de problème de consommation de CPU (80%-98%). Si tu veux c'est le moment où tout roule comme sur des roulettes ...
Emmanuel T.
Je suis sur que tu as surement deja executer ceci:
Est ce que tu peux nous dire ce que ca donne ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 WITH Waits AS (SELECT wait_type, wait_time_ms / 1000. AS wait_time_s, 100. * wait_time_ms / SUM(wait_time_ms) OVER() AS pct, ROW_NUMBER() OVER(ORDER BY wait_time_ms DESC) AS rn FROM sys.dm_os_wait_stats WHERE wait_type NOT IN( 'SLEEP_TASK', 'BROKER_TASK_STOP', 'SQLTRACE_BUFFER_FLUSH', 'CLR_AUTO_EVENT', 'CLR_MANUAL_EVENT', 'LAZYWRITER_SLEEP')) -- filter out additional irrelevant waits SELECT W1.wait_type, CAST(W1.wait_time_s AS DECIMAL(12, 2)) AS wait_time_s, CAST(W1.pct AS DECIMAL(12, 2)) AS pct, CAST(SUM(W2.pct) AS DECIMAL(12, 2)) AS running_pct FROM Waits AS W1 INNER JOIN Waits AS W2 ON W2.rn <= W1.rn GROUP BY W1.rn, W1.wait_type, W1.wait_time_s, W1.pct HAVING SUM(W2.pct) - W1.pct < 95; -- percentage threshold
Quand au perfmon, c'est vrai que ca ne sert a rien...
=> Repasser en SIMPLE. C'est un travail de fourmi de passer tous les prédicats un par un et rechercher des anomalies dans les histogrammes. Un exemple simple: une table PERSONNEL comporte une colonne de genre, avec 1 million de ligne. Sur un population de 1 million d'individus, 990000 sont des femmes et le reste sont des hommes. Si tu passes SELECT NOM, PRENOM FROM PERSONNEL WHERE GENRE='H', la valeur de recherche est discriminante, donc l'optimiseur doit considérer de passer par l'index sur GENRE.
Dans le cas où PARAMETERIZATION est à SIMPLE, l'optimiseur est très conservateur et peut choisir de ne pas paramétriser la requête, parce que la distribution des valeurs n'est pas uniforme. Il va calculer un plan pour GENRE='H' et un plan pour GENRE='F'. Si tu passe sur FORCED, il ne va pas se poser la question, il va réutiliser le premier plan compilé, qui ne sera pas forcément le bon.
David B.
Etienne ZINZINDOHOUE
Billets-Articles
Etienne ZINZINDOHOUE
Billets-Articles
Constat
------------------
Lorsqu'on arrête le service de l'application client, le consommation CPU sur le serveur SQL redevient normal (<50%).
Une fois le service (application client) démarré l'utilisation de CPU est voisine de 100%.
En utilisant les DMVs, on retrouve dans le TOP 10 des requêtes les plus exécutées une requête du genre :
Qu'elle est le but de cette requête ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part IF EXISTS (SELECT * FROM Instance.Base.schema.Table WHERE id LIKE @id) ....
Comme c'est une application orienté "centre d'appel", il me semble que cette requête vérifie le type d'interaction(appel téléphonique,e-mail,...) pour identifier le type d'interaction a envoyé au télé-conseillé...
Et la table "Instance.Base.schema.Table" compte environ une vingtaine de colonnes et contient actuellement plus de 5 millions de lignes.
Et comme je n'ai pas la main sur cette requête je ne peux pas la modifier !
Héééé oui (Voilà l'avantage d'écrire du SQL en dur dans l'application au lieu d'utiliser des procédures stockées!!! et quelle requête SQL d'ailleurs ???)
Cette requête qui pourrait être optimisée en écrivant une requête du genre :
ou
Code : Sélectionner tout - Visualiser dans une fenêtre à part IF EXISTS (SELECT id FROM Instance.Base.schema.Table WHERE id = @id) ....
Action
Code : Sélectionner tout - Visualiser dans une fenêtre à part IF EXISTS (SELECT id,col1,col2 FROM Instance.Base.schema.Table WHERE id = @id) ....
--------------
1.) Une purge de quelques tables est planifié
2.) Un CASE ouvert chez l'éditeur pour qu'il optimise les requêtes incriminées !
Mais avant de prendre cette dernière décision il faut d'abord convaincre les collaborateurs... Rien de plus convainquant qu'une Démo ;-) Que vous pouvez aussi voir ici
En tout cas merci à vous tous pour votre soutien
A+
Etienne ZINZINDOHOUE
Billets-Articles
L'optimisation suggeree sur la requete existante presentee ici sera inutile.
IF EXIST verifie l'existance d'au moins une ligne repondant a la query et ne remonte aucun resultat.
Test effectue:
Resultats:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 set statistics io on if exists (select * from table where colonne = 20000) select 1 if exists (select colonne from table where colonne = 20000) select 1
Table 'table'. Scan count 1, logical reads 4, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
(1 row(s) affected)
Table 'table'. Scan count 1, logical reads 4, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
(1 row(s) affected)
La table "table" contenant 63989971 rows et est constituee de 56 colonnes.
Refais ton test en utilisant une requête du genre :
Et donne-nous le résultat. Tu peux voir une démo ici pour plus de détails
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 DECLARE @id int SET @id = 20000 IF EXISTS (SELECT * FROM table WHERE colonne LIKE @id) SELECT1
A +
Etienne ZINZINDOHOUE
Billets-Articles
Resultats identiques:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10 set statistics io on DECLARE @id bigint SET @id = 20000 IF EXISTS (SELECT * FROM table WHERE colonne = @id) SELECT 1 IF EXISTS (SELECT colonne FROM table WHERE colonne = @id) SELECT 1
Table 'table'. Scan count 1, logical reads 4, physical reads 4, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
(1 row(s) affected)
Table 'table'. Scan count 1, logical reads 4, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
(1 row(s) affected)
Les 4 lectures physiques sont effectuees pour monter les donnees en memoire au premier run de la query.
Le second contient deja l'info.
Resultat des memes requetes apres un second run:
Table 'table'. Scan count 1, logical reads 4, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
(1 row(s) affected)
Table 'table'. Scan count 1, logical reads 4, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
(1 row(s) affected)
Ta demo est basee sur un ordre select simple qui dans ce cas, je suis d'accord, remontera differents resultats en fonction de la selection d'un set de colonnes limite ou l'utilisation de *.
C'est pas le cas dans une clause IF EXISTS.
Tu as lu très rapidement ce que je te demande de faire. Je vais encore me répéter : Refais le test avec
puis
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 DECLARE @id bigint SET @id = 20000 IF EXISTS (SELECT * FROM table WHERE colonne LIKE @id) SELECT 1
Et montre nous surtout les plans d'exécution
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 DECLARE @id bigint SET @id = 20000 IF EXISTS (SELECT colonne FROM table WHERE colonne = @id) SELECT 1
A+
Etienne ZINZINDOHOUE
Billets-Articles
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager