Eu tenho FILE_A, que possui mais de 300.000 linhas, e FILE_B, que possui mais de 30 milhões de linhas. Criei um script Bash que greps cada linha em FILE_A em FILE_B e grava o resultado do grep em um novo arquivo.
Todo esse processo leva mais de 5 horas.
Como posso melhorar o desempenho do meu script?
Estou usando grep -F -m 1
como o comando grep. FILE_A aparece assim:
123456789
123455321
e FILE_B é assim:
123456789,123456789,730025400149993,
123455321,123455321,730025400126097,
Então, com o Bash, tenho um while
loop que escolhe a próxima linha em FILE_A e a coloca em FILE_B. Quando o padrão é encontrado em FILE_B, eu o escrevo no arquivo result.txt.
while read -r line; do
grep -F -m1 $line 30MFile
done < 300KFile
algorithms
performance
perl
bash
rogerio_marcio
fonte
fonte
Aqui está uma resposta Perl para a posteridade. Eu faço isso rotineiramente para combinar linhas de 1 milhão a 30-35 milhões de linhas. Demora cerca de 10 segundos para terminar.
Primeiro, faça o hash do arquivo FILE_A:
Então, se seu arquivo grande estiver delimitado e souber qual coluna seguir, verifique apenas a existência da chave de hash ao executar FILE_B, o que é muito, muito mais rápido do que verificar a correspondência de igualdade ou expressão regular:
Se o seu arquivo de destino maior não puder ser analisado de maneira adequada, esse script perderá seu valor, uma vez que grande parte de sua velocidade vem de não ter que ativar o mecanismo de expressão regular .
fonte
Se você não se importa com alguma programação mais envolvida, considere usar árvores de sufixos (ou uma variante).
Você pode pré-processar
FILE_B
usando o algoritmo de Ukkonen em tempo linear. Em seguida, você consulta cada linha noFILE_A
tempo linear no comprimento da linha e obtém todos os números de linhas correspondentes (pode ser necessário adaptar um pouco a árvore) que você pode gravar em um arquivo de resultado.Todo o procedimento é executado no tempo O (n + Nm) se n é o comprimento de
FILE_B
,N
é o número de linhas emFILE_A
e m é o comprimento da linha mais longaFILE_A
- esse é o tempo de execução essencialmente linear. Supera o tempo quadrático que sua abordagem original precisa por magnitudes.fonte
Encontrei a
--mmap
bandeira recentemente, não tive a chance de testá-la, mas ficarei feliz em saber das suas descobertas. Aqui está a descrição da página de manual:Veja isto ou isto para mais informações sobre
mmap
.fonte
--mmap
dose não despeja nada, eu recomendaria uma corrida com--mmap
e uma sem. E então usewc
para ver se você tem a mesma quantidade de saída - este deve ser um teste robusto, considerando que executamos 2 vezes o grep e apenas uma flag diferia.Por que você não coloca esse arquivo em um banco de dados? Os bancos de dados são realmente bons para fazer uma junção eficiente de mesclagem, hash e loop aninhado dessa maneira. E eles são realmente bons em utilizar memória virtual
fonte