Pergunta

Eu tenho um conjunto muito grande de dados (~3 milhões de registros) que precisa ser mesclado com atualizações e novos registros diariamente.Eu tenho um procedimento armazenado que realmente divide o conjunto de registros em 1.000 blocos de registros e usa o MERGE comando com tabelas temporárias na tentativa de evitar o bloqueio da tabela ativa enquanto os dados estão sendo atualizados.O problema é que isso não ajuda exatamente.A tabela ainda “trava” e nosso site que utiliza os dados recebe timeouts ao tentar acessar os dados.Eu até tentei dividi-lo em 100 pedaços de registro e até tentei um WAITFOR DELAY '000:00:5' para ver se ajudaria fazer uma pausa entre a fusão dos pedaços.Ainda é bastante lento.

Estou procurando sugestões, práticas recomendadas ou exemplos sobre como mesclar grandes conjuntos de dados sem bloquear as tabelas.

Obrigado

Foi útil?

Solução

Mude seu front-end para usar NOLOCK ou READ UNCOMMITTED ao fazer o Selecione% s.

Você não pode NOLOCK MERGE,INSERT ou UPDATE, pois os registros devem ser bloqueados para realizar a atualização.No entanto, você pode NOLOCK os SELECTS.

Observe que você deve usar isso com cautela.Se leituras sujas estiverem corretas, vá em frente.No entanto, se as leituras exigirem os dados atualizados, você precisará seguir um caminho diferente e descobrir exatamente por que a fusão de registros 3M está causando um problema.

Aposto que a maior parte do tempo é gasta lendo dados do disco durante o comando de mesclagem e/ou trabalhando em situações de pouca memória.Talvez seja melhor simplesmente colocar mais memória RAM em seu servidor de banco de dados.

Uma quantidade ideal seria ter memória RAM suficiente para colocar todo o banco de dados na memória, conforme necessário.Por exemplo, se você tiver um banco de dados de 4 GB, certifique-se de ter 8 GB de RAM.em um servidor x64, é claro.

Outras dicas

Receio ter tido a experiência oposta.Estávamos realizando atualizações e inserções onde a tabela de origem tinha apenas uma fração do número de linhas da tabela de destino, que estava na casa dos milhões.

Quando combinamos os registros da tabela de origem em toda a janela operacional e realizamos o MERGE apenas uma vez, observamos um aumento de 500% no desempenho.Minha explicação para isso é que você está pagando pela análise inicial do comando MERGE apenas uma vez, em vez de repetidamente em um loop apertado.

Além disso, tenho certeza de que a fusão de 1,6 milhão de linhas (fonte) em 7 milhões de linhas (destino), em oposição a 400 linhas em 7 milhões de linhas em 4.000 operações distintas (no nosso caso), aproveita muito melhor os recursos do mecanismo do servidor SQL.Novamente, uma boa parte do trabalho consiste na análise dos dois conjuntos de dados e isso é feito apenas uma vez.

Outra pergunta que devo fazer é se você está ciente de que o comando MERGE tem um desempenho muito melhor com índices nas tabelas de origem e de destino.Gostaria de encaminhá-lo para o seguinte link:

http://msdn.microsoft.com/en-us/library/cc879317(v=SQL.100).aspx

Por experiência pessoal, o principal problema do MERGE é que, como ele bloqueia a página, ele impede qualquer simultaneidade nos seus INSERTs direcionados a uma tabela.Portanto, se você seguir esse caminho, é fundamental agrupar todas as atualizações que chegarão a uma tabela em um único gravador.

Por exemplo:tínhamos uma tabela na qual INSERT demorava uns loucos 0,2 segundos por entrada, a maior parte desse tempo aparentemente sendo desperdiçado no travamento de transações, então mudamos para o uso de MERGE e alguns testes rápidos mostraram que isso nos permitiu inserir 256 entradas em 0,4 segundos ou mesmo 512 em 0,5 segundos, testamos isso com geradores de carga e tudo parecia estar bem, até que atingiu a produção e tudo foi bloqueado nos bloqueios de página, resultando em uma taxa de transferência total muito menor do que com os INSERTs individuais.

A solução foi não apenas agrupar as entradas de um único produtor em uma operação MERGE, mas também agrupar o lote dos produtores que vão para o banco de dados individual em uma única operação MERGE por meio de um nível adicional de fila (anteriormente também uma única conexão por banco de dados, mas usando MARS para intercalar todas as chamadas dos produtores para o procedimento armazenado fazendo a transação MERGE real), desta forma conseguimos lidar com muitos milhares de INSERTs por segundo sem problemas.

Ter as dicas do NOLOCK em todas as suas leituras de front-end é sempre uma necessidade absoluta.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top