SMO, SSMS sont lents pour la gestion de SQL Server dans Docker lors de la connexion à localhost

9

TL; DR: lors de la connexion à mon conteneur SQL Server Docker via un nom qui se résout en boucle IPv6 ( ::1), les appels SMO sont vraiment lents. Lors de l'utilisation 127.0.0.1, ils sont rapides.


J'essaie d'apprendre à utiliser l'image Docker microsoft / mssql-server-windows-developer . Selon la documentation de Microsoft, ce conteneur expose uniquement le port 1433 TCP.

docker run -d -p 1433:1433 -e sa_password=Passw0rd! -e ACCEPT_EULA=Y -v C:\dockerdb:C:\dockerdb microsoft/mssql-server-windows-developer

J'exécute le conteneur sur Windows 10 et j'ai réussi à le démarrer, à m'authentifier avec l'authentification SQL Server et à exécuter des requêtes sur l'instance à l'aide de sqlcmd et SSMS 17.4 sur l'hôte Windows (connexion à localhost ou «.») Et à SQL Operations Studio sur un mac à côté se connectant par IP. Je ne vois aucun problème de performances notable lors de l'exécution de requêtes de cette façon.

Dans SSMS, je peux également parcourir l'explorateur d'objets, mais si j'essaie de faire quelque chose à partir du menu contextuel sur un objet dans l'explorateur d'objets, comme ouvrir la fenêtre des paramètres d'instance ou attacher une base de données, SSMS n'affiche pas de réponse pendant environ 5 -10 minutes, moment auquel il affiche la fenêtre que j'ai demandée ou affiche ce message d'erreur:

Message d'erreur SSMS

J'essaie également de faire des scripts PowerShell contre cette instance à l'aide de l'objet SMO Scripter et de voir le même type de comportement. Le script PS parcourt les objets de la base de données et les scripte dans un fichier, et bien qu'il fonctionne pour rassembler la liste des objets relativement rapidement, chaque objet individuel prend 5 à 10 minutes pour être scripté - trop lent pour être utilisable.

J'ai l'impression que le seul port exposé n'est pas suffisant et que SMO et SSMS essaient de se connecter d'une manière similaire, ce qui les ralentit. Se pourrait-il également que lors de la connexion à localhost, ces outils supposent la présence d'autres canaux de communication qui ne seraient généralement pas protégés par un pare-feu? Y a-t-il des paramètres de connexion supplémentaires que je pourrais utiliser? Quelqu'un peut-il valider mon hypothèse selon laquelle SSMS utilise SMO ou autre chose pour parler à SQL Server?


MISE À JOUR: J'étudie toujours, mais il est plausible qu'il s'agit d'un problème Docker autour des contraintes de ressources. C'est déroutant car la plupart de la documentation semble indiquer que les conteneurs Windows n'ont pas de contraintes de ressources par défaut (et celles-ci ne peuvent pas être définies dans l'interface graphique de Docker pour Windows - uniquement pour les conteneurs Linux ), mais il semble qu'en réalité, Windows les conteneurs fonctionnant sous Windows 10 obtiennent une allocation de RAM par défaut de 1 Go. J'essaie toujours de comprendre comment inspecter un conteneur en cours d'exécution pour voir son allocation de RAM et de CPU, mais je dois ensuite essayer d'augmenter ceux-ci à partir des valeurs par défaut, en utilisant des docker runparamètres.


NOUVELLE MISE À JOUR: Je n'ai pas réussi à obtenir une sorte de mesure fiable de Docker qui me dise quelles limites CPU et mémoire il a en place pour le conteneur. Des recherches variables indiquent que les conteneurs Docker n'ont pas de limite de mémoire par défaut, ou qu'ils le font et que c'est 1 Go, mais tout ce que je peux vérifier pour le moment, c'est que docker statsle conteneur SQL utilise uniquement entre 750 et 850 mégaoctets, et quand J'essaie d'ajouter un paramètre d'exécution pour définir la mémoire disponible à 4 Go, cela génère des erreurs. J'ai donc arrêté de suivre ce fil d'interrogation et j'ai fait un autre test: en entrant dans une session PowerShell interactive sur le conteneur en cours d'exécution, puis en invoquant mon script PowerShell lié ci-dessus depuis l' intérieur du conteneur.

En cours d'exécution à l'intérieur du conteneur, il n'y avait aucun problème. Il a explosé à travers 2780 objets en seulement quelques minutes. Je pense que cela confirme que le problème concerne la frontière conteneur / hôte, donc je vais voir si je peux ouvrir ce port UDP. MISE À JOUR: L' ouverture du port 1434 UDP n'a pas aidé.


PLUS DE MISES À JOUR - Solution de contournement obtenue, pas un problème de contrainte de ressources: il semble y avoir des problèmes liés à la définition d'allocations de mémoire importantes pour les conteneurs Windows - je recevais des erreurs similaires pour 3g et 2g, mais j'ai finalement pu démarrer le conteneur avec 1,5 g, et J'ai vu une différence dans le docker statsconteneur qui (je pense) confirme qu'il fonctionnait avec une allocation par défaut de 1 Go. Sur les paramètres par défaut, la statistique PRIV WORKING SET (pour laquelle je ne trouve aucune documentation, mais ma meilleure supposition est la RAM) se situe entre 700 Mo et 850 Mo. Avecdocker run —memory="1.5g"réglé, il est d'environ 1,0 Go. Il a donc augmenté, mais semble laisser une plus grande partie de l'allocation gratuite qu'auparavant. J'interprète cela (peut-être à tort) comme signifiant que ce serveur (qui n'exécute absolument AUCUNE charge et n'a AUCUNE base de données utilisateur) n'est pas sous pression mémoire. J'ai vérifié le paramètre de mémoire maximale du serveur pour confirmer qu'il est défini sur le maximum par défaut de 2PiB.

Ensuite, les choses sont devenues étranges. Je teste toujours des choses en exécutant mon script PowerShell à partir de divers endroits. Rapide à l'intérieur du conteneur, lent sur l'hôte. Ensuite, j'ai effectué un RDP sur une autre machine Windows sur le réseau et exécuté le script à partir de cette machine, en me connectant à mon hôte Windows 10 par IP. Et c'était RAPIDE! Cela semble soutenir la théorie selon laquelle lors de la connexion à quelque chose qui est censé être localhost, SMO essaie de se connecter à SQL Server en utilisant autre chose que le port 1433 TCP, qui attend un très long délai avant de retomber sur la connexion TCP.

J'ai décidé d'essayer de valider cette théorie en entrant une entrée de fichier hosts pour faire référence à localhost par un nom autre que localhost:

        127.0.0.1       dockersucks

Je me suis connecté dans SSMS à dockersucks au lieu de localhost ou ".", Et immédiatement les choses ont été plus rapides. Naviguer dans l'explorateur d'objets était comme d'habitude, et ouvrir des panneaux comme attacher des propriétés de base de données ou de serveur s'est produit aussi rapidement que d'habitude. Et, lorsque j'ai exécuté mon script PowerShell à partir de l'hôte Windows 10 en utilisant cet alias comme nom de serveur, cela a également été rapide.

J'ai ajouté cette mise à jour à la question au lieu d'une réponse car je cherche toujours une explication de la raison pour laquelle cela se produit et s'il existe un moyen de le corriger pour les connexions à "localhost" par ce nom.

NReilingh
la source
Peut-être que votre instance de docker est juste sous-alimentée? S'il s'agissait d'un problème de port, je doute que vous le voyiez fonctionner, donc je ne passerais pas beaucoup de temps sur cette voie.
LowlyDBA
Oui, j'y pensais, mais les performances des requêtes semblent bonnes, donc elles semblent limitées à certains types d'actions. J'ai également besoin de tester l'exécution des trucs SMO à l'intérieur du conteneur et de vérifier que le problème n'y est pas présent.
NReilingh
1
Je n'ai pas raté cette partie. SQL Server utilise le regroupement de connexions. J'obtiens que c'est frustrant, mais je veux aussi vous impressionner pour vous assurer que le conteneur (ou "bizarre Hyper-V lite VM" dans ce cas) a suffisamment de RAM. Votre script PS s'est exécuté "rapidement", mais les minutes pour parcourir ~ 3000 objets sont lentes dans une machine avec suffisamment de RAM (c'est-à-dire plus de 2 Go).
Randolph West
1
Pour être parfaitement honnête, vous feriez probablement mieux de lancer une machine virtuelle Ubuntu Hyper-V sur votre machine et d'installer SQL Server pour Linux sur cela.
Randolph West
1
@bazzilic J'explique pourquoi dans ma réponse. Veuillez y faire part de vos commentaires si vous avez besoin d'éclaircissements.
NReilingh

Réponses:

3

Il s'agit très probablement d'un problème de famine RAM.

A vérifier:

  • Le conteneur dispose-t-il de 4 Go de RAM? Vérifiez cette réponse .
  • Avez-vous configuré le paramètre Max Server Memory pour SQL Server dans le conteneur? Selon la quantité de RAM que SQL Server peut voir dans le conteneur, cela peut être défini sur une valeur comprise entre 1 Go et 3,25 Go.
  • La mémoire RAM de votre hôte est-elle utilisée et est-il possible que Docker effectue une pagination sur le disque? Fermez toutes les applications étrangères (les navigateurs Web sont de gros consommateurs de RAM). SSMS a besoin d'environ 1 Go de RAM de travail pour être utilisable.
  • Est-ce plus rapide après un redémarrage?

Si je faisais cela moi-même, j'installerais Docker Community Edition pour Windows à partir du magasin Docker , puis installer l' image Docker SQL Server de cette façon.

Si votre connexion Internet est suffisamment rapide, vous pouvez être opérationnel en moins de 5 minutes et être en mesure d'allouer les ressources de manière beaucoup plus simple.

EDIT: Ah, le réseautage.

Randolph West
la source
Je ne sais pas si vous comprenez mal cela, mais je n'exécute pas SSMS à l' intérieur du conteneur. Ce n'est pas possible, car les conteneurs Windows ne prennent actuellement pas en charge les connexions RDP ou les interfaces graphiques. Je sais déjà que SQL Server n'est pas lent - mais j'ai besoin de savoir si je mets à faim ce conteneur Docker pour des ressources. L'hôte Windows 10 exécutant le conteneur et SSMS a 10 Go de RAM et 2 cœurs, mais je ne sais pas combien est alloué au conteneur.
NReilingh
Ma réponse a été réécrite
Randolph West
Voir la mise à jour Q pour plus d'informations. Notez qu'il s'agit de la propre construction d'image de conteneur de Microsoft, donc je pense que nous sommes assez sûrs en supposant que les paramètres dans le conteneur ne seront pas un problème.
NReilingh
2
Veuillez ne pas faire cette supposition!
Randolph West
@NReilingh J'ai ajouté une URL à ma réponse pour que vous examiniez l' -moption.
Randolph West
3

La principale différence ici est de savoir si SSMS / SMO tente de se connecter avec IPv4 ou IPv6. Si vous effectuez une opération ping localhostdans une invite de commande, vous devriez la voir se résoudre en ::1, ce qui est l'équivalent IPv6 de 127.0.0.1. Se connecter à .fait la même chose.

Votre docker runcommande expose uniquement le port 1433 127.0.0.1. Vous pouvez le vérifier en exécutant netstat -apour voir quels ports sont disponibles.

L'alias de fichier d'hôtes que vous avez créé se résout directement 127.0.0.1, mais vous n'en avez pas besoin, car vous pouvez vous connecter 127.0.0.1directement dans SSMS et résoudre votre problème de cette façon. Désactiver IPv6 entièrement sur votre système hôte fonctionnerait probablement aussi, mais je ne sais pas à quel point cela est conseillé sur Windows 10.

J'envisagerai une autre réponse pour accepter si quelqu'un peut me dire pourquoi IPv6 est à l'origine de cette rupture.

NReilingh
la source
Avez-vous essayé de vous connecter à TCP: localhost? Il se peut que SSMS / SMO tentent une connexion de mémoire partagée ou de canaux nommés lorsque le nom est localhost ou (local) ou même "." et 1. Je ne sais pas si SSMS 17.4 utilise définitivement SMO dans l'Explorateur d'objets, mais je pense que c'est possible.
Monsieur Magoo
@MisterMagoo La saisie tcp:localhostdans le champ du nom du serveur ne semble pas fonctionner du tout, mais j'avais essayé de spécifier explicitement TCP / IP dans les propriétés de connexion sans amélioration. Je pense toujours que le problème est un repli lent vers 127.0.0.1localhost en cas d' ::1échec. Je pense que mes fenêtres de requête fonctionnaient parce qu'elles maintenaient une connexion, alors que mon script utilisant SMO créait (peut-être) de nouvelles connexions encore et encore.
NReilingh
1
@NReilingh Je vois ce même problème - votre dépannage et explication ont été vraiment utiles. L'adressage de mon conteneur de serveur SQL comme 127.0.0.1 ( pas localhost ) à partir de mon environnement hôte était le seul moyen pour que les connexions hôte à conteneur fonctionnent normalement.
rogersillito