O desempenho da pastilha aumenta sob carga: por que?

19

Eu tenho um pedaço de código que executa inserções em tabelas altamente desnormalizadas. As tabelas têm um número de colunas variando de ~ 100 a 300+. Este é o SQL Server 2008 R2, em execução no Windows Server 2008.

Cada inserção consiste em inserir em várias tabelas sob a mesma transação. Algumas inserções são agrupadas em lotes pelo NHibernate, mas outras não, mas estão todas na mesma transação.

Quando executo inserções, digamos 500 vezes, chamando repetidamente um pedaço de código que executa a inserção, recebo uma média de ~ 360 ms.

O estranho é que, quando executo o código de teste simultaneamente usando 4 processos (o mesmo exe é executado a partir de 4 prompts de comando diferentes no windows server 2008), o desempenho da inserção por chamada fica muito melhor. Vejo rajadas que chegam a 90 ms (quase X4 mais rápido). Estou medindo o tempo de inserção do código.

Como os quatro processos não sabem nada um do outro, suponho que isso tenha algo a ver com o SQL Server, mas não faço a menor idéia do porquê. Gostaria de saber por que isso está acontecendo e se há alguma configuração que me permita obter o mesmo desempenho quando as inserções não são tão frequentes.

Sugestões sobre os métodos de monitoramento do SQL Server para entender o que está acontecendo no nível do banco de dados são igualmente bem-vindas.

mahonya
fonte

Respostas:

15

Uma razão possível é que quatro processos simultâneos geram um padrão mais favorável de liberações de log - normalmente significa que cada liberação de log grava mais dados do que no caso de um único processo de execução.

Para determinar se o tamanho da taxa de transferência / liberação do log de transações é um fator, monitore:

Procure limites internos sendo atingidos. No SQL Server 2008 R2, pode haver no máximo 32 E / S de liberação de log (assíncronas) pendentes por banco de dados em versões de 64 bits (apenas 8 em 32 bits). Há também um limite de tamanho total para os excelentes IOs de 3840 KB.

Mais informações e leituras adicionais:

Paul White diz que a GoFundMonica
fonte
12

Tudo o que @PaulWhite diz, mais ...

Se você tiver chaves estrangeiras, todas as inserções exigirão uma verificação em cada tabela mencionada. Parece-me que você está, pois você está recebendo apenas 360ms, o que me parece lento.

De qualquer forma, verificar essas tabelas é massivamente ajudado por ter esses dados na RAM, em vez de precisar carregá-los no disco.

Parece-me que carregar os dados na RAM é uma parte significativa da sua execução e que isso só precisa acontecer uma vez.

Também pode ser um cache de plano eficaz e que suas consultas precisam ser compiladas na primeira vez, com chamadas subseqüentes sendo capazes de evitar essa fase.

Rob Farley
fonte
Obrigado Rob. Meu problema de desempenho está associado ao alto número de tabelas usadas durante uma inserção. Não há chaves estrangeiras, eu as removi por motivos de desempenho, e meus requisitos de modelo e domínio me permitem fazer isso. Não estou carregando dados para a RAM e minhas inserções são modeladas dinamicamente pelas solicitações recebidas, que mudam o tempo todo. Basicamente, estou abusando de um esquema de estrela / floco de neve (ish) para OLTP e tentando fugir com o melhor desempenho possível.
Mahonya
2
@mahonya, mesmo que você não esteja carregando explicitamente dados na RAM, o SQL Server deve primeiro ler o índice e as páginas de dados necessárias no cache do buffer antes de executar a operação de inserção. Threads de inserção simultâneos podem ter o efeito de aquecer o cache, de modo que um thread incorre na sobrecarga de leitura e o outro acesse os dados no cache.
Dan Guzman
Obrigado @DanGuzman - e sim, mahonya, há uma grande chance de seu cache estar sendo bem aquecido. Eu verificaria suas esperas para ver se a E / S física está causando seu gargalo.
22816 Rob Farley
Obrigado @DanGuzman Concordou, a aceleração do cache do índice db é algo que eu estou acostumado a ver no postgres. Provavelmente não entendi a entrada de Rob.
Mahonya
-3

alguns servidores / cpus / os lembram os padrões. como cache.

Como você faz a mesma coisa quatro vezes, tenho certeza de que há maneiras de cortar custos. O que eu acho que é a primeira maneira de fazê-lo, ele pensa nisso como um processo longo (exemplo1), mas da segunda maneira is vê o código reutilizado e o executa como cache (exemplo2) ou pode ser o primeiro processo a ser grande demais para caber tudo no (exemplo ram 3).

example1: 0111110000110111110000111011111000011110111110000

exemplo2: 0111110000 | 11 | 0111110000 | 111 | 0111110000 | 1111 | 0111110000

exemplo3: 0111110000011111000001111100000111110000 exemplo3: loop: 0111110000

Eu sei que o servidor ubuntu faz isso com repetidas consultas mysql. Posso salvá-los no cache, embora realmente a única diferença no tempo seja 10-40mms, mas isso se soma. Quando eu estava na escola, houve aulas que mostraram que você precisa fazer com que os programas (perl / php) usem esse cache para ser mais rápido.

Mas, pode depender do programa, em que idioma é, em que é compilado ou como foi programado.

Bryku
fonte