Array
(
)

Threads Simultâneas

Melantonio
|
MVP
Pontos: 300
    27 out 2010

Boa tarde pessoal, estou com o seguinte problema:

tenho que fazer um carga semanal em uma tabela, como a regra é um pouco complexa eu resolvi criar um robô ao invês de fazer um JOB chamar um PROC.

O robô funciona legal, mas como a quantidade de registros é muito grande, eu gostaria de criar threads para fazer esse insert mais rápido. Tenho cerca de 14 milhões de linhas a serem incluídas.

Alguem pode da alguma idéia de como fazer isso?

Obrigado.

Vinicius Vieira
   - 27 out 2010

Declara algumas propriedades do tipo Thread na classe que você está fazendo, e cria um método que faz a inserção na tabela se você quer fazer em paralelo cola dentro do método que insere um while inserindo um registro por vez de mil e mil e você tem que garantir que como eles estão executando em paralelo que o que um método inseriu o outro não vai inserir de novo eu aconselho você pegar uma quantidade de registro por exemplo 1000 e jogar em memória marcar esses mil como processando e passar dentro dessa coleção inserindo um a um no banco acabou a thread ela chama novamente um método da thread principal que restarta ela se ainda houverem registros para serem inseridos , agora vou mostrar um exemplo de como ficaria isso.
public class InsercaoBD{Thread trd1;Thread trd2;
privatedelegate void EncapsulaVoid();
private EncapsulaVoid m_StartaThread1;private EncapsulaVoid m_StartaThread2;
Inserir(){ List<Registro> lst = new List<Registros>(); lst =  GetRegitros(1000);//Escreva um método que retorne x registros que estão para serem inseridos MarcaRegistro(lst,Processando);//Escreva outro que marca uma lista de registros como processando o método que pega não pode trazer os que estão marcados dessa forma foreach(Regitro rs in lst){ insere(rs);//Um método que grava o registro no banco } MarcaRegistro(lst,Processado);//Muda o status para processado; this.Invoke(m_StartaThread1); this.Invoke(m_StartaThread2); } StartaThreads(){   trd1 = new Thread(Inserir); trd2 = new Thread(Inserir); m_StartaThread1 = new EncapsulaVoid(StartaThread1); m_StartaThread2 = new EncapsulaVoid(StartaThread2); trd1.Start(); trd2.Start(); } StartaThread1(){   if(GetQtdRegistroFaltantes>0){ trd1 = new Thread(Inserir); trd1.Start(); } } StartaThread2(){       if(GetQtdRegistroFaltantes>0){ trd2 = new Thread(Inserir); trd2.Start(); } }
}

Vinicius Vieira
   - 27 out 2010

Ve se eu consegui ser claro meu camarada e se era isso mesmo que você queria, lembrando que eu utilizaria o job mesmo se fosse sql server.Atenciosamente.

Luiz Soares
   - 27 out 2010

opa...14M/semana?

acho que é melhor jogar um pouco desse processamento pro banco mesmo..pq vai segurar bastante recurso da maquina que estiver esse robo, mas se acha que a maquina aguenta, ainda assim acho que inserir um por um é enfiar uma faca no olho. Melhor processar em lote ai, pode seguir a ideia que o Vinicius ja passou ai so que ao inves de processar os 1000 um por um, pega 1000 gera um lote e manda pro banco de uma vez.

Vinicius Vieira
   - 28 out 2010

A inserção de um em um é para evitar lock da tabela, de 1000 em 1000, enquanto uma thread está inserindo 1000 a outra aguarda ela terminar e já começar inserir mais mil dessa forma iria ficar meio sem sentido o uso da thread e sem contar que iria travar a tabela durante quase todo o processo de inserção em massa, colocando de uma em uma assim o banco normalmente consegue administrar você loca, insere e libera, se tiver alguém esperando para realizar uma outra ação em determinado momento o banco vai realizar essa solicitação, e volta novamente o ciclo normal loca insere libera, entendeu? fica mais fácil dele realizar solicitações de outras conexões. Te digo isso pois já teve caso em que precisei dar um update em uma tabela que recebia muita movimentação 24 horas e só consegui fazer o update quando coloquei ele dentro de um while atualizando um por um, qualquer outra tentativa de realizar isso em lotes falhava.