SMO, SSMS são lentos para o gerenciamento do SQL Server no Docker ao se conectar ao host local

9

TL; DR: Ao conectar-se ao meu contêiner do SQL Server Docker por meio de um nome que resolve o loopback do IPv6 ( ::1), as chamadas SMO são realmente lentas. Ao usar 127.0.0.1, eles são rápidos.


Estou tentando aprender como usar a imagem do Docker microsoft / mssql-server-windows-developer . Segundo a documentação da Microsoft, esse contêiner expõe apenas a porta 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

Estou executando o contêiner no Windows 10 e tive êxito em iniciá-lo, autenticando com autenticação do SQL Server e executando consultas na instância usando sqlcmd e SSMS 17.4 no host do Windows (conectando-se ao host local ou ".") E SQL Operations Estúdio em um mac next door conectando por IP. Não vejo problemas visíveis de desempenho ao executar consultas dessa maneira.

No SSMS, também posso procurar o explorador de objetos, mas se tentar fazer algo no menu do botão direito do mouse em um objeto no explorador de objetos, como abrir a janela de parâmetros da instância ou anexar um banco de dados, o SSMS não mostrará uma resposta por cerca de 5 -10 minutos, momento em que exibe a janela solicitada ou exibe esta mensagem de erro:

Mensagem de erro do SSMS

Também estou tentando executar scripts do PowerShell nessa instância usando o objeto SMO Scripter e ver o mesmo tipo de comportamento. O script PS percorre os objetos no banco de dados e os rotula para arquivar e, embora ele trabalhe para reunir a lista de objetos de maneira relativamente rápida, cada objeto individual leva de 5 a 10 minutos para o script - lento demais para ser utilizável.

Eu tenho um palpite de que a única porta exposta não é suficiente e que o SMO e o SSMS estão tentando se conectar de uma maneira semelhante que os torna mais lentos. Também pode ser que, ao conectar-se ao host local, essas ferramentas considerem que existem outros canais de comunicação presentes que normalmente não seriam protegidos por firewall? Existem parâmetros de conexão adicionais que eu poderia estar usando? Alguém pode validar minha suposição de que o SSMS está usando SMO ou outra coisa para conversar com o SQL Server?


ATUALIZAÇÃO: Ainda estou investigando, mas é plausível que esse seja um problema do Docker relacionado a restrições de recursos. Isso é confuso, porque a maioria da documentação parece indicar que os Contêineres do Windows não têm restrições de recursos padrão (e elas não podem ser definidas na GUI do Docker for Windows - apenas para contêineres do Linux ), mas parece que, na realidade, o Windows os contêineres em execução no Windows 10 recebem uma alocação de RAM padrão de 1 GB. Ainda estou tentando descobrir como inspecionar um contêiner em execução para ver sua alocação de RAM e CPU, mas, em seguida, tenho que tentar aumentá-los, independentemente dos padrões, usando docker runparâmetros.


ATUALIZAÇÃO ADICIONAL: Falha ao obter qualquer tipo de métrica confiável da janela de encaixe que me diga quais limites de CPU e memória ela possui para o contêiner. Pesquisas variadas indicam que os contêineres do docker não têm um limite de memória por padrão, ou que possuem e é de 1 GB, mas tudo o que posso verificar no momento é que docker statso contêiner SQL está usando apenas entre 750 e 850 meg e quando Eu tento adicionar um parâmetro de execução para definir a memória disponível para 4 gb, erros. Então, parei de seguir esse segmento de perguntas e fiz uma verificação intestinal diferente: entrar em uma sessão interativa do PowerShell no contêiner em execução e depois chamar meu script do PowerShell vinculado acima de dentro do contêiner.

Correndo dentro do contêiner, não havia problema. Ele percorreu 2780 objetos em apenas alguns minutos. Acho que isso confirma que o problema está no limite do contêiner / host, então vou ver se consigo abrir a porta UDP. ATUALIZAÇÃO: Abrir a porta 1434 UDP não ajudou.


MAIS ATUALIZAÇÕES - Solução alternativa alcançada, não é um problema de restrição de recursos: Parece haver problemas relacionados à configuração de grandes alocações de memória para contêineres do Windows - eu estava recebendo erros semelhantes para 3G e 2G, mas finalmente consegui iniciar o contêiner com 1,5g e Vi uma diferença no docker statscontêiner que (acho) confirma que estava sendo executado com uma alocação padrão de 1 GB. Nas configurações padrão, a estatística PRIV WORKING SET (para a qual não encontro documentação, mas meu melhor palpite é que é RAM) está entre 700MiB e 850MiB. Comdocker run —memory="1.5g"conjunto, é em torno de 1.0GiB. Por isso, expandiu-se, mas parece estar deixando mais da alocação livre do que antes. Eu interpreto isso (talvez incorretamente) para significar que este servidor (que está executando absolutamente SEM carga e NÃO possui bancos de dados de usuário) não está sob pressão de memória. Verifiquei a configuração de memória máxima do servidor para confirmar se está definida no máximo padrão de 2PiB.

Então as coisas ficaram estranhas. Ainda estou testando as coisas executando meu script do PowerShell de vários locais. Rápido dentro do contêiner, lento no host. Então eu fiz o RDP para outra máquina Windows na rede e executei o script dessa máquina, conectando-me ao meu host do Windows 10 por IP. E foi RÁPIDO! Isso parece apoiar a teoria de que, ao conectar-se a algo que deveria ser host local, o SMO está tentando se conectar ao SQL Server usando algo diferente da porta 1433 TCP, que aguarda um tempo limite muito longo antes de retornar à conexão TCP.

Decidi tentar validar essa teoria inserindo uma entrada de arquivo hosts para se referir ao localhost por um nome diferente de localhost:

        127.0.0.1       dockersucks

Conectei o SSMS ao dockersucks em vez do localhost ou ".", E imediatamente as coisas ficaram mais rápidas. Navegar no explorador de objetos era como de costume, e abrir painéis como anexar banco de dados ou propriedades do servidor acontecia o mais rápido possível. E, quando executei meu script do PowerShell no host do Windows 10 usando esse alias como o nome do servidor, ele também foi rápido.

Eu adicionei esta atualização à pergunta em vez de uma resposta, pois ainda estou procurando uma explicação sobre o motivo disso estar ocorrendo e se existe uma maneira de corrigi-la para conexões com "localhost" com esse nome.

NReilingh
fonte
Talvez sua instância do docker esteja com pouca energia? Se fosse um problema de porta, duvido que você estivesse vendo tudo funcionar, para que eu não passasse muito tempo nessa estrada.
LowlyDBA
Sim, eu estava pensando sobre isso, mas o desempenho da consulta parece bom, por isso parece limitado a apenas certos tipos de ações. Também preciso testar a execução do material SMO do DENTRO do contêiner e verificar se o problema não está presente lá.
NReilingh
11
Eu não perdi essa parte. O SQL Server usa o pool de conexões. Entendo que isso é frustrante, mas também quero impressioná-lo para garantir que o contêiner (ou "VM estranha do Hyper-V lite" nesse caso)) tenha RAM suficiente. Seu script PS foi executado "rapidamente", mas os minutos para percorrer ~ 3000 objetos são lentos em uma máquina com RAM suficiente (ou seja, mais de 2 GB).
Randolph West
11
Para ser sincero, provavelmente é melhor criar uma VM do Ubuntu Hyper-V em sua máquina e instalar o SQL Server para Linux nela.
Randolph West
11
@bazzilic Eu explico o porquê na minha resposta. Comente lá se precisar de esclarecimentos.
NReilingh

Respostas:

3

Provavelmente, esse é um problema de falta de memória RAM.

Coisas a verificar:

  • O contêiner possui 4 GB de RAM atribuídos a ele? Verifique esta resposta .
  • Você definiu a configuração de Memória máxima do servidor para o SQL Server dentro do contêiner? Dependendo da quantidade de RAM que o SQL Server pode ver no contêiner, isso pode ser definido entre 1 GB e 3,25 GB.
  • A RAM do seu host está esgotada e é possível que o Docker esteja paginando em disco? Feche todos os aplicativos estranhos (os navegadores da Web são grandes consumidores de RAM). O SSMS precisa de cerca de 1 GB de RAM de trabalho para ser usado.
  • Isso é mais rápido após uma reinicialização?

Se eu estivesse fazendo isso pessoalmente, instalaria o Docker Community Edition para Windows no repositório do Docker e depois instalaria a imagem do SQL Server Docker dessa maneira.

Se a sua conexão à Internet for rápida o suficiente, você poderá estar em funcionamento em menos de 5 minutos e alocar recursos de uma maneira muito mais fácil.

EDIT: Ah, redes.

Randolph West
fonte
Não tenho certeza se você está entendendo errado, mas não estou executando o SSMS dentro do contêiner. Isso não é possível, pois os contêineres do Windows atualmente não oferecem suporte a conexões RDP ou GUIs. Eu já sei que o SQL Server não é lento - mas preciso descobrir se estou morrendo de fome neste contêiner de docker por recursos. O host do Windows 10 que executa o contêiner e o SSMS tem 10 GB de RAM e 2 núcleos, mas não tenho certeza de quanto está sendo alocado para o contêiner.
NReilingh
Minha resposta foi reescrito
Randolph Oeste
Consulte Q update para obter informações adicionais. Observe que essa é a criação da imagem de contêiner da própria Microsoft, então acho que estamos bastante seguros assumindo que as configurações no contêiner não serão um problema.
NReilingh
2
Por favor, não faça essa suposição!
Randolph West
@NReilingh Adicionei um URL à minha resposta para você investigar a -mopção.
Randolph West
3

A principal diferença aqui é se o SSMS / SMO está tentando se conectar ao IPv4 ou IPv6. Se você fizer um ping localhostem um prompt de comando, deverá resolver ::1, qual é o equivalente ao IPv6 127.0.0.1. Conectar-se a .faz a mesma coisa.

Seu docker runcomando expõe apenas a porta 1433 127.0.0.1. Você pode verificar isso executando netstat -apara ver quais portas estão disponíveis.

O alias do arquivo de hosts que você criou resolve diretamente 127.0.0.1, mas não é necessário, pois você pode se conectar 127.0.0.1diretamente no SSMS e resolver seu problema dessa maneira. Desativar o IPv6 inteiramente em seu sistema host provavelmente também funcionará, mas não tenho certeza de quão recomendável é isso no Windows 10.

Considerarei uma resposta alternativa a ser aceita se alguém puder me dizer por que o IPv6 está causando isso.

NReilingh
fonte
Você já tentou se conectar ao tcp: localhost? Pode ser que o SSMS / SMO esteja tentando uma conexão de memória compartilhada ou pipes nomeados quando o nome for host local ou (local) ou mesmo "." e 1. Não sei se o SSMS 17.4 definitivamente usa o SMO no Object Explorer, mas acho que é possível.
Mister Magoo
@MisterMagoo A entrada tcp:localhostno campo de nome do servidor parece não funcionar, mas tentei especificar explicitamente o TCP / IP nas propriedades da conexão sem aprimoramento. Ainda acho que o problema é o fallback lento 127.0.0.1para o host local quando ::1falha. Acho que minhas janelas de consulta estavam funcionando porque estavam mantendo uma conexão, enquanto meu script usando SMO estava (talvez) criando novas conexões repetidamente.
NReilingh
11
@NReilingh Estou vendo esse mesmo problema - sua solução de problemas e suas explicações foram realmente úteis. Endereçar meu contêiner de servidor sql como 127.0.0.1 ( não localhost ) no meu ambiente host era a única maneira de conseguir que as conexões host a contêiner funcionassem normalmente.
Rogersillito