Minha empresa usa um aplicativo que apresenta problemas de desempenho bastante importantes. Há vários problemas no banco de dados em que estou trabalhando, mas muitos deles são puramente relacionados ao aplicativo.
Na minha investigação, descobri que existem milhões de consultas no banco de dados do SQL Server que consultam tabelas vazias. Temos cerca de 300 tabelas vazias e algumas dessas tabelas são consultadas até 100-200 vezes por minuto. As tabelas não têm nada a ver com nossa área de negócios e são essencialmente partes do aplicativo original que o fornecedor não removeu quando elas foram contratadas pela minha empresa para produzir uma solução de software para nós.
Além do fato de suspeitarmos que nosso log de erros do aplicativo está sendo inundado por erros relacionados a esse problema, o fornecedor garante que não há impacto no desempenho ou na estabilidade do aplicativo ou do servidor de banco de dados. O log de erros é inundado na medida em que não podemos ver mais de 2 minutos de erros para fazer diagnósticos.
O custo real dessas consultas obviamente será baixo em termos de ciclos de CPU, etc. Mas alguém pode sugerir qual seria o efeito no SQL Server e no aplicativo? Eu suspeitaria que a mecânica real de enviar uma solicitação, confirmá-la, processá-la, devolvê-la e confirmar o recebimento pelo aplicativo teria um impacto no desempenho.
Usamos o SQL Server 2008 R2, Oracle Weblogic 11g para o aplicativo.
@ Frisbee- Para encurtar a história, criei uma tabela contendo o texto da consulta que atingiu as tabelas vazias no banco de dados do aplicativo e, em seguida, consultei todos os nomes de tabela que eu sei que estão vazios e recebi uma lista muito longa. O maior sucesso foi em 2,7 milhões de execuções em 30 dias de atividade, tendo em mente que o aplicativo geralmente está em uso das 8 às 18 horas, para que esses números sejam mais concentrados nas horas operacionais. Múltiplas tabelas, várias consultas, provavelmente algumas relavent via junções, outras não. O maior sucesso (2,7 milhões na época) foi uma simples seleção de uma única tabela vazia com uma cláusula where, sem junções. Eu esperaria que consultas maiores com junções às tabelas vazias incluíssem atualizações nas tabelas vinculadas, mas vou verificar isso e atualizar esta pergunta o mais rápido possível.
Atualização: existem 1000 consultas com uma contagem de execução entre 1043 - 4622614 (mais de 2,5 meses). Vou ter que cavar mais para descobrir quando o plano em cache se origina. Isso é apenas para lhe dar uma idéia da extensão das consultas. A maioria é razoavelmente complexa, com mais de 20 junções.
@ srutzky- sim, acredito que exista uma coluna de data relacionada a quando o plano foi compilado, para que seja de seu interesse, por isso vou verificar. Gostaria de saber se os limites de encadeamento seriam um fator quando o SQL Server estiver em um cluster VMware? Em breve será um Dell PE 730xD dedicado, felizmente.
@Frisbee - Desculpe pela resposta tardia. Como você sugeriu, eu executei um select * da tabela vazia 10.000 vezes em 24 threads usando o SQLQueryStress (na verdade, 240.000 iterações) e atingi 10.000 solicitações em lote / s imediatamente. Reduzi para 1000 vezes mais de 24 threads e atingi pouco menos de 4.000 solicitações em lote / s. Eu também tentei 10.000 iterações em apenas 12 threads (so 120000 iterações totais) e isso produziu 6.505 lotes / s sustentados. O efeito na CPU foi realmente perceptível, em torno de 5 a 10% do uso total da CPU durante cada execução de teste. As esperas na rede eram insignificantes (como 3ms com o cliente na minha estação de trabalho), mas o impacto na CPU estava lá, com certeza, o que é bastante conclusivo para mim. Parece resumir-se ao uso da CPU e um pouco de E / S desnecessária de arquivo de banco de dados. O total de execuções / segundo funciona em pouco menos de 3000, que é mais do que em produção, no entanto, estou testando apenas uma das dezenas de consultas como essa. O efeito líquido de centenas de consultas atingindo tabelas vazias a uma taxa entre 300-4000 vezes por minuto, portanto, não seria desprezível no que diz respeito ao tempo da CPU. Todos os testes foram feitos em um PE 730xD inativo com matriz de flash duplo e 256 GB de RAM, 12 núcleos modernos.
@ srutzky- bom pensamento. O SQLQueryStress parece usar o pool de conexões por padrão, mas eu dei uma olhada de qualquer maneira e descobri que sim, a caixa de pool de conexões está marcada. Atualize para seguir
@ srutzky- O pool de conexões aparentemente não está ativado no aplicativo - ou, se estiver, não está funcionando. Fiz um rastreamento do criador de perfil e descobri que as conexões têm EventSubClass "1 - Não em pool" para eventos de Logon de Auditoria.
RE: Pool de conexões - Verificou os weblogics e encontrou o pool de conexões ativado. Executou mais rastreamentos contra sinais ao vivo e encontrou que o pool não está ocorrendo corretamente / de modo algum:
E aqui está o que parece quando executo uma única consulta sem junções em uma tabela preenchida; as exceções exibem "Ocorreu um erro relacionado à rede ou à instância ao estabelecer uma conexão com o SQL Server. O servidor não foi encontrado ou não estava acessível. Verifique se o nome da instância está correto e se o SQL Server está configurado para permitir conexões remotas. (provedor: provedor de pipes nomeados, erro: 40 - Não foi possível abrir uma conexão com o SQL Server) "Observe o contador de solicitações em lote. Executar ping no servidor durante o tempo em que as exceções são geradas resulta em uma resposta de ping bem-sucedida.
Atualização - duas execuções de teste consecutivas, mesma carga de trabalho (selecione * deEmptyTable), pool ativado / não ativado. Um pouco mais de uso da CPU e muitas falhas e nunca ultrapassa 500 solicitações em lote / s. Os testes mostram 10.000 lotes / s e nenhuma falha com o pool LIGADO, e cerca de 400 lotes / s, em seguida, muitas falhas devido à desativação do pool. Gostaria de saber se essas falhas estão relacionadas à falta de disponibilidade de conexão?
@ srutzky- Selecione Contagem (*) em sys.dm_exec_connections;
Pool ativado: 37 de forma consistente, mesmo após o teste de carga ser interrompido
Pool desabilitado: 11-37, dependendo da ocorrência ou não de exceções
no SQLQueryStress, isto é: quando essas calhas aparecem no
gráfico Lotes / s, as exceções ocorrem no SQLQueryStress e o
número de conexões cai para 11 e, em seguida, volta gradualmente para 37 quando os lotes começam a atingir o pico e as exceções não estão ocorrendo. Muito, muito interessante.
O número máximo de conexões nas instâncias de teste / ao vivo é definido como o padrão 0.
Verificamos os logs do aplicativo e não conseguimos encontrar problemas de conectividade, no entanto, existem apenas alguns minutos disponíveis devido ao grande número e tamanho de erros, ou seja: muitos erros de rastreamento de pilha. Um colega no suporte a aplicativos recomenda que ocorra um número substancial de erros de HTTP relacionados à conectividade. Parece que, por algum motivo, o aplicativo não está agrupando corretamente as conexões e, como resultado, o servidor está ficando repetidamente sem conexões. Vou examinar mais os logs de aplicativos. Gostaria de saber se existe uma maneira de provar que isso está acontecendo na produção do lado do SQL Server?
@ srutzky- Obrigado. Amanhã vou verificar a configuração da weblogic e atualizar. Eu estava pensando sobre as meras 37 conexões - se SQLQueryStress está executando 12 threads em 10.000 iterações = 120.000 instruções de seleção sem pool, isso não significa que cada seleção cria uma conexão distinta com a instância sql?
@ srutzky- Weblogics estão configurados para agrupar conexões, então deve estar funcionando bem. O pool de conexões é configurado assim, em cada um dos 4 weblogics com balanceamento de carga:
- Capacidade inicial: 10
- Capacidade máxima: 50
- Capacidade mínima: 5
Quando eu aumento o número de threads executando a consulta de seleção de tabela vazia, o número de conexões atinge um pico em torno de 47. Com o pool de conexões desabilitado, vejo consistentemente um número máximo de solicitações em lote / segundo mais baixo (de 10.000 para cerca de 400). O que acontece sempre é que as 'exceções' no SQLQueryStress ocorrem logo após os lotes / s entrarem em um vale. Está relacionado à conectividade, mas não consigo entender exatamente por que isso está acontecendo. Quando nenhum teste está sendo executado, #connections cai para cerca de 12.
Com o pool de conexões desabilitado, estou tendo problemas para entender por que as exceções ocorrem, mas talvez seja uma questão totalmente diferente de stackExchange / Adam Machanic?
@srutzky Gostaria de saber então por que as exceções ocorrem sem o pool ativado, mesmo que o SQL Server não esteja ficando sem conexões?
SELECT COUNT(*) FROM sys.dm_exec_connections;
para verificar se o valor é muito diferente entre ter o pool ativado ou não. Com base nesses erros, acho que haveria muito mais conexões quando o pool estiver desativado.
Pooling=false
ou Max Pool Size
?