Instruction SELECT distante lente en raison du long «temps de traitement client», mais rapide localement

12

Lorsqu'elle est connectée à notre serveur de production (SQL Server 2008, machine très puissante), cette instruction SELECT prend 2 secondes , crachant tous les champs (4 Mo de données au total).

SELECT TOP (30000) *
FROM person
WITH(NOLOCK);

À partir de n'importe quelle autre boîte sur le même réseau (connexion en utilisant l'authentification SQL ou l'authentification Windows), la même requête prend 1 minute, 8 secondes .

Je teste avec cette déclaration très simple pour illustrer qu'il ne s'agit pas d'un problème d'indexation ou d'un problème lié aux requêtes. (Nous avons actuellement des problèmes de performances avec toutes les requêtes ...)

Les rangées viennent en morceaux, et pas en même temps. J'obtiens mes premières lignes instantanément, puis j'attends plus d'une minute pour que les lots de lignes entrent.

Voici les statistiques client de la requête, lorsqu'elle est exécutée à partir de la boîte distante:

Query Profile Statistics
  Number of INSERT, DELETE and UPDATE statements 0
  Rows affected by INSERT, DELETE, or UPDATE statements 0
  Number of SELECT statements  2
  Rows returned by SELECT statements 30001
  Number of transactions 0

Network Statistics
  Number of server roundtrips 3
  TDS packets sent from client        3
  TDS packets received from server 1216
  Bytes sent from client         266
  Bytes received from server 4019800

Time Statistics
  Client processing time 72441 ms (72 seconds)
  Total execution time   72441 ms
  Wait time on server replies 0

Nous pouvons voir que le «temps de traitement client» est égal au temps d'exécution total.

Quelqu'un sait-il quelles mesures je peux prendre pour diagnostiquer pourquoi le transfert des données réelles prend du temps?

Existe-t-il un paramètre de configuration SQL qui restreint ou limite la vitesse de transfert de données entre les machines?

FranticRock
la source
Soit dit en passant, nous avons essayé de copier le fichier de même taille (4 Mo) entre le serveur de base de données et une autre boîte, et cela a pris une seconde. Cela ne semble donc pas être un problème de réseau.
FranticRock
Qu'est-ce que l'application cliente? SSMS sur les postes de travail des utilisateurs finaux?
Thomas Stringer
Oui Microsoft SQL Server Management Studio 10.50.1600.1. 2008 R2
FranticRock
Ce problème a commencé depuis que nous avons déplacé les centres de données et la machine entière a été réinstallée (tout y compris SQL). Nous sommes avec un hébergeur très respectable.
FranticRock

Réponses:

5

Votre problème est définitivement lié au réseau, basé sur vos informations. En tant que tel, il doit être traité avec des professionnels du réseau (ce n'est pas moi).

Choses qui pourraient aider:

  • Cartes NIC plus rapides (sur le serveur SQL).
  • Ajout d'une carte NIC / sous-réseau spécifique / allouée entre les serveurs (serveur Web et SQL Server).

Le serveur Web est-il dans le même sous-réseau que le serveur SQL?

Y a-t-il des routeurs / ponts, etc. entre eux?

Pas beaucoup de changements possibles sur le serveur SQL:

  • Les données de sortie sont envoyées par SQL Server avec MS "TDS protocol" propriétaire.
  • La taille par défaut du tampon TDS est de 4 Ko. Voir dans MSDB: "Option de taille de paquet réseau"
  • La compression des données (avec SQL Server ou une application externe) - dépend de la nature des données.

Vous utilisez une taille par défaut: consultez vos statistiques: "Paquets TDS reçus du serveur 1216" (4MB / 1K = 4KB). Oui, la taille du tampon TDS peut être modifiée: voir dans google: "TDS protocol batch size"

Bonne discussion sur le sujet: "la taille des paquets réseau de sql détermine-t-elle vraiment le trafic aller-retour?"

Cependant, la modification de la taille du boîtier TDS aura (inévitablement) des effets imprévisibles et ne devrait être utilisée en production que dans des cas exceptionnels.

Un changement d'architecture ou l'introduction de la mise en cache des données sur le niveau intermédiaire serait également utile.

alexei
la source
8

Ce problème est maintenant résolu.

C'était un problème de réseau, et la boîte SQL utilisait une carte NIC de 100 Mo / s , au lieu d'une carte NIC de 10 Go / s ...

Un changement de configuration réseau pour utiliser la bonne carte réseau a résolu le problème. Nous obtenons maintenant des performances similaires pour toutes les requêtes de la zone Production SQL et des autres zones du réseau.

Merci à tous pour votre aide.

FranticRock
la source
J'ai exactement le même problème que vous et je veux vérifier quelle carte NIC mon SQL Server utilise. Où puis-je voir ça?
Misha Zaslavsky
3

À la lecture initiale, il semble que vous rencontriez des problèmes de latence du réseau. Avez-vous regardé certains des compteurs Network Perfmon? Ceux-ci peuvent vous donner une indication de ce qui se passe avec le réseau.

Citation de Quels compteurs Perfmon dois-je surveiller et que signifie chacun d'eux?

NETWORK IO

Pour mesurer les E / S réseau, vous pouvez utiliser les compteurs suivants:

Interface réseau Octets Total / sec

Seuil: valeurs soutenues de plus de 80% de la bande passante du réseau.

Signification: ce compteur indique la vitesse à laquelle les octets sont envoyés et reçus sur chaque carte réseau. Ce compteur vous aide à savoir si le trafic sur votre carte réseau est saturé et si vous devez ajouter une autre carte réseau. La rapidité avec laquelle vous pouvez identifier un problème dépend du type de réseau dont vous disposez et du partage de la bande passante avec d'autres applications.

Interface réseau Octets reçus / s

Ce compteur indique la vitesse à laquelle les octets sont reçus sur chaque carte réseau. Vous pouvez calculer le taux de données entrantes en tant que partie de la bande passante totale. Cela vous aidera à savoir que vous devez optimiser les données entrantes du client ou que vous devez ajouter une autre carte réseau pour gérer le trafic entrant.

Interface réseau Octets envoyés / s

Ce compteur indique la vitesse à laquelle les octets sont envoyés sur chaque carte réseau. Vous pouvez calculer le taux de données entrantes en tant que partie de la bande passante totale. Cela vous aidera à savoir que vous devez optimiser les données envoyées au client ou que vous devez ajouter une autre carte réseau pour gérer le trafic sortant.

ServerBytes Total / sec

Cette valeur ne doit pas dépasser 50% de la capacité du réseau.

Ce compteur indique le nombre d'octets envoyés et reçus sur le réseau. Des valeurs plus élevées indiquent la bande passante réseau comme goulot d'étranglement. Si la somme des octets total / s pour tous les serveurs est à peu près égale aux taux de transfert maximum de votre réseau, vous devrez peut-être segmenter le réseau.

Temps d'interruption du processeur%

Ce compteur indique le pourcentage de temps que le processeur passe à recevoir et à réparer les interruptions matérielles. Cette valeur est un indicateur indirect de l'activité des appareils qui génèrent des interruptions, tels que les adaptateurs réseau.

Interface réseau (*) Longueur de la file d'attente de sortie

Ce compteur vérifie le nombre de threads en attente sur la carte réseau. S'il y a beaucoup de threads en attente sur la carte réseau, le système saturera très probablement les E / S du réseau, probablement en raison de la latence du réseau ou de la bande passante du réseau.

La longueur de la file d'attente de sortie est la longueur de la file d'attente des paquets de sortie (en paquets). Si celle-ci est supérieure à deux, il y a des retards et le goulot d'étranglement doit être trouvé et éliminé, si possible. Étant donné que les demandes sont mises en file d'attente par la spécification d'interface de pilote réseau (NDIS) dans cette implémentation, ce sera toujours 0.

jgardner04
la source
Après avoir surveillé ces statistiques dans Perfmon, j'ai remarqué quelques choses. Le nombre total d'octets / s ne dépasse jamais 700 K / s sur aucune des cartes réseau. Même si j'exécute une requête qui demande des mégaoctets de données, ce nombre reste à environ 500K / sec. Notre bande passante est de 100 MBPS, et nous n'obtenons même pas 1% d'utilisation. Je pense qu'il devrait y avoir une limite configurée quelque part qui oblige à réduire la taille des paquets ou à limiter le taux de transfert. Les interruptions matérielles / s sont à 700-2000. La file d'attente de sortie est vide. L'utilisation de la carte réseau culmine à environ 4% au maximum.
FranticRock
2
Il pourrait y avoir un décalage entre la vitesse de la carte réseau et le port du commutateur. Avez-vous engagé votre équipe réseau pour l'examiner du côté des commutateurs?
jgardner04
2

Quelques questions préliminaires: 1) Le serveur a un client SQL sur Prod. configuration de la machine serveur, non? Donc, si vous faites la même requête à partir du client situé sur la même machine, elle sera terminée en 2 secondes? Avez-vous essayé de faire ça? Est-ce vraiment 2 secondes? 2) Vous avez mentionné que la configuration de votre environnement de production a été modifiée (ou que le serveur de production a été déplacé vers un autre réseau / la reconstruction totale du serveur est terminée), non? Quel était le temps de consommation des requêtes dans l'ancien environnement de production?

Depuis n'importe quelle autre boîte du même réseau ... la même requête prend 1 minute et 8 secondes. 3) Vous dites que la requête revient et est consommée par le client, situé sur n'importe quelle machine du réseau donné (sauf votre machine spécifique) en environ 70 secondes? J'ai bien compris? 3.1 Par ailleurs, quel est le calendrier de consommation de cette requête, acceptable par l'entreprise? 4) Cependant, vous spécifiez que pour un ordinateur client spécifique que vous utilisez, le temps de consommation de sortie de la requête est: Temps d'exécution du client 15:30: 48 15 minutes? (et cette fois n'est clairement pas acceptable)? Correct? 5) le problème est donc limité à une seule machine cliente? Ou vers N'IMPORTE QUELLE machine client / intermédiaire, etc. (dans un nouvel environnement)? 6) quel est le délai indiqué par le ping? de l'ordinateur client au serveur? 7) Vous (ou l'administrateur réseau) avez exécuté tracert dans les deux sens (du client au serveur, du serveur au client)? Combien de houblon? Quel est le temps combiné? 8) L'ancien réseau de production est-il vivant? Pouvez-vous comparer en utilisant Ping et Traceroute - quel était le temps et les sauts entre le client et le serveur là-bas?

Par curiosité: c'est un exemple de la requête? ou la formulation exacte de la requête? La requête ne contient vraiment PAS de clause WHERE? D'accord avec moi que c'est très inhabituel .. La table a un index clusterisé ou est un tas? Le tableau contient combien de lignes au total? Le tableau est fortement fragmenté? Par curiosité: pourquoi avoir choisi SELECT TOP NNN? Pourquoi ne pas SET ROWCOUNT NNN - puis SELECT *? Cette requête est émise combien de fois par le client par jour? 1? 100? 1MLN? Les données sous-jacentes sont statiques ou dynamiques et ont-elles beaucoup changé? Combien (0,01% par jour? 1% par jour? 10% par jour?) La sortie de la requête est traitée par programme? (pas par un utilisateur?) Pourquoi n'est-il pas mis en cache / pas stocké sur le niveau intermédiaire? merci, Alexei

alexei
la source
Merci beaucoup pour l'info. Mes réponses ci-dessous. 1. Correct. Les outils clients sont également installés sur prod, et la même requête que j'ai mentionnée prend 2 secondes pour renvoyer tous les 30 000 enregistrements (totalisant 4 Mo). Soit dit en passant, la requête que j'ai utilisée n'est qu'un exemple. Ce n'est pas une vraie requête commerciale. C'est juste un moyen d'obtenir 4 Mo de données à partir d'une table. Nous avons actuellement un problème de performances en lisant plusieurs mégaoctets de données à partir de n'importe quelle table avec n'importe quelle requête actuellement.
FranticRock
2. Le temps de consommation était proche, sinon le même que celui de la même requête exécutée localement à partir de la zone PROD. (IE 2 secondes) 3. C'est vrai 1 min 8 secondes est le temps d'exécution. Cette durée varie selon les différentes machines clientes. Depuis notre machine de développement (située beaucoup plus loin que la machine de scène), j'ai exécuté cette requête 8 fois de suite, et le temps variait de 11 secondes à 22 secondes. (moyenne 18 sec.)
FranticRock
depuis notre boîte de développement tracert Prod_IP_Address 1 53 ms 52 ms 53 ms SQL2008 Depuis la scène, le temps est constamment supérieur à 1 minute. tracert Prod_IP_Address tracert: 1 1 ms <1 ms <1 ms SQL2008 Depuis le serveur Web de production: le temps d'exécution est de 53 secondes. tracert: 1 1 ms <1 ms <1 ms SQL2008
FranticRock
4. La colonne supérieure "Client Execution Time" est juste l'heure locale de la machine (IE: 15:30:00) 5. Le problème se produit sur n'importe quelle machine frappant le serveur DB de production, y compris sur notre serveur Web de production. 6. Le délai de ping est <1 MS de la zone d'étape à la zone prod SQL. 7. Veuillez voir ci-dessus. 8. Malheureusement, l'ancien réseau n'existe plus.
FranticRock
Il est vraiment intéressant de noter que même si DEV envoie une requête de 53 ms, l'exécution de la requête ne prend que 11 à 22 secondes. Alors que la scène envoie un ping à 1 MS, le retour des données prend plus d'une minute. Dev est également beaucoup plus éloigné géographiquement. Et la scène est juste à côté de la boîte de production, et pourtant elle prend beaucoup plus de temps.
FranticRock