Com licença, com licença, por obséquio alguém poderia me ajudar?
Tenho que realizar um processamento de um arquivo .txt que possui aproximadamente 150.000 linhas, sendo que cada linha deve ser analisada e processada (entenda-se como persistida a informação no banco de dados) automaticamente. Esse processamento já consigo fazer, porém, está demorando em torno de 7 horas para concluir.
Então decidir fazer uma thread que realize esse processamento de forma paralela, mas nas minhas pesquisas na web encontrei algumas informações de que as threads não são executadas exatamente em um processamento paralelo mas existe a possibilidade de se codificar a thread de forma a utilizar todos os núcleos disponíveis no processador, porém, não encontrei nenhum exemplo prático a esse respeito.
7 horas para processar 150.000 linhas é muita coisa. Dificilmente threads te ajudarão com isso. Além disso, você vai ter um gargalo na tabela da mesma maneira. Antes de pensar em threads, sugiro analisar o seu código e pensar nos seguintes pontos:
você está usando PreparedStatement nas suas queries ? Com isso você compila a query uma única vez no banco de dados, e dá uma diferença absurda
como você está abrindo e fechando transações ?
já tentou usar inserção em batches ?
como você está usando as conexões ? está abrindo a conexão uma única vez ?
Joga em uma tabela intermediária do jeito que estiver. Quando tiver no banco, tudo ficará mais rápido para analisar e jogar na tabela definitiva, de preferencia através de stored procedure, sem overhead de outro programa.
Esse sistema tem logs?
Ele loga tudo?
Acho relevante inserir mais logs, antes do início e ao término da execução de toda e qualquer estrutura lógica: if, else, for, etc.
Estou usando o SQL Server mesmo, mas não é viável a utilização deste recurso, o servidor de banco é um servidor isolado, no qual a conexão à máquina só se dá por meio de VPN e apenas a porta do banco (1433) está aberta para conexão das aplicações.
Bem, criei uma tabela de controle, o preenchimento desta tabela ocorre em 4 minutos, sem realizar o tratamento dos dados, ou seja, os dados são armazenados tal qual está no arquivo.
Estou usando JPA e para esta classe especifica, sim, estou abrindo e fechando conexões a cada 1000 registros persistidos.
Em geral, logs apresentam saída padronizada, informando o horário em que ele foi gerado. A partir destes registros, você consegue identificar qual é o trecho de código onde a lentidão se apresenta e focar as ações ali.
Um detalhe que me chamou a atenção é o fato de você ter comentado:
Isso pode ser um fator (ou o fator) causador da lentidão. Logo, se você colocar 10 threads para acessar via VPN, o efeito pode ser contrário, visto que, haverá concorrência para acesso ao recurso e, como o @rmendes08 disse, deadlocks.
Nesse caso, uma das otimizações possíveis é abrir a sessão do JPA uma única vez e fechá-la somente no final do processamento. Ao invés de criar/destruir sessões você pode abrir uma transação para cada 1000 registros.
De qualquer maneira, eu particularmente não gosto de usar JPA para tarefas de ETL, pois há todo um overhead para manter suas entidades sincronizadas com o contexto de persistência.
Bem, em resumo, não temos acesso ao servidor de banco, pro motivos de segurança, apenas à instância do banco de dados, não acredito que esse seja o “gargalo”.
Eu estava fazendo exatamente isso, mas depois de alguns minutos de processamento, o JBoss me retornava um erro dizendo que a conexão com o banco foi reiniciada. Por esse motivo tive de controlar as transações por meio da anotação @TransactionManagement(TransactionManagementType.BEAN)
Isso nao é impedimento, se está na VPN tem acesso, afinal sua aplicacao já se conecta ao banco e executa comandos SQL. BULK INSERT é mais um comando SQL. Seu arquivo txt pode ficar em um caminho de rede compartilhado (se isso for impedimento, ai nao tem jeito mesmo de usar).
Independente disso, pelo amor de Deus nao use JPA/Hibernate, puro overhead.
Cara estou lendo um arquivo .csv e tenho que analisar os dados e fazer uma inserção no PostgreSQL o arquivo aqui tem umas 47.000 linhas demora cerca de 1 Hora e 10 para processar e o pior o sistema é em Web, faço o upload e bem a coisa não esta muito elegante porque a pagina fica parada só tem um Aguarde … para o usuário.
Tarefas como esta pra quem esta começando e pega um trabalho destes fica difícil de manejar como fazer de forma correta, estou usando Spring Data JPA, vou ler aqui os comentários porque não estou muito feliz com o que fiz nesta rotina.
Eu recomendo abrir um tópico separado para o seu problema. Apesar de ser parecido com o problema do colega é comum ter réplicas e tréplicas, e as coisas podem ficar misturadas e confusas.