Estou procurando algoritmos de classificação que possam funcionar com uma grande quantidade de dados, ou seja, que funcionem mesmo quando todo o conjunto de dados não puder ser mantido na memória principal de uma só vez.
O único candidato que eu encontrei até agora é a classificação por mesclagem: é possível implementar o algoritmo de forma que ele varra seu conjunto de dados em cada mesclagem sem manter todos os dados na memória principal de uma só vez. A variação da classificação de mesclagem que tenho em mente é descrita neste artigo na seção Usar com unidades de fita .
Eu acho que essa é uma boa solução (com complexidade O (nx log (n)), mas estou curioso para saber se existem outros algoritmos de classificação (possivelmente mais rápidos) que podem funcionar em grandes conjuntos de dados que não cabem na memória principal.
EDITAR
Aqui estão mais alguns detalhes, conforme exigido pelas respostas:
- Os dados precisam ser classificados periodicamente, por exemplo, uma vez em um mês. Não preciso inserir alguns registros e ter os dados classificados de forma incremental.
- Meu arquivo de texto de exemplo tem cerca de 1 GB de texto UTF-8, mas eu queria resolver o problema em geral, mesmo que o arquivo tivesse, digamos, 20 GB.
- Ele não está em um banco de dados e, devido a outras restrições, não pode estar.
- Os dados são despejados por outros como um arquivo de texto, eu tenho meu próprio código para ler esse arquivo de texto.
- O formato dos dados é um arquivo de texto: os novos caracteres de linha são separadores de registros.
Uma possível melhoria que eu tinha em mente era dividir o arquivo em arquivos pequenos o suficiente para serem classificados na memória e, finalmente, mesclar todos esses arquivos usando o algoritmo que descrevi acima.
fonte
Respostas:
A referência canônica sobre classificação e pesquisa é Knuth, vol. 3 . Comece por aí.
O livro foi originalmente escrito quando os computadores eram muito menores e mais lentos do que são agora, o que tornou as técnicas de classificação por falta de memória mais importantes do que se pensa hoje.
fonte
A mesclagem externa do R-Way, como no
sort
comando UNIX, é uma boa alternativa. Pela sua formulação, não tenho certeza se esse é o algoritmo que você quis dizer com "classificação por mesclagem" e, se você não o conhece, dê uma olhada.fonte
Sem mais detalhes, "Merge Sort" é provavelmente a melhor resposta que você terá, no entanto, você pode implementar algo muito mais inteligente, dependendo de seus requisitos.
Por exemplo, você pode simplesmente criar um índice na memória do arquivo e copiar todos os valores de uma vez, armazenando em cache o local de vários valores-chave? 1/2 cabe na memória de uma só vez ou 1/1000000? Se for o segundo, talvez você não consiga encaixar um índice na memória; se o primeiro, você pode classificar as duas metades com mais eficiência e depois fundi-las em uma única e última etapa.
Inferno, como você não especificou, é possível que todos os seus dados estejam em um banco de dados. Nesse caso, é possível criar uma tabela de índice e chamar de boa (acho que não é esse o caso, mas apenas apontando sua situação é crítica para resolver um problema complicado como esse).
Se você quiser fazer isso apenas uma vez e estiver procurando por um hack muito rápido, parece que esse tipo de mesclagem externa seria um bom começo se você estiver executando o unix (uma vez que aparentemente está embutido)
Se você precisar mantê-lo em ordem e sempre adicionar um único registro, será necessária uma classificação de inserção (adicionar um único registro aos dados classificados é sempre uma classificação de inserção).
Você pode controlar o código que "lê" os dados? Nesse caso, muitas formas de indexação (em vez de classificar movendo dados pelo disco) ajudarão MUITO (será realmente um requisito absoluto).
Então:
fonte
Se você realmente deseja uma solução escalável, consulte o TeraSort, a implementação de classificação padrão com redução de mapa; mais detalhes sobre o StackOverflow .
fonte
Você pode estar interessado em uma classificação de balde . O desempenho médio do caso é tempo linear.
= O (n + d) n: número de elementos ed = comprimento do maior número se você tiver uma intuição sobre seus dados, ou seja. Se você souber quantos 'dígitos' é o seu maior número. Portanto, se você possui 2 milhões de números de 6 dígitos => 0 (n), portanto, linear.
fonte
Use o algoritmo de classificação de mesclagem externa (se seus dados forem contínuos) ou uma classificação de bucket com classificação de contagem como uma implementação de classificação para buckets (se seus dados forem discretos e distribuídos uniformemente).
Provavelmente, a melhor abordagem é criar seu próprio arquivo de índice / mapeamento se o incremento for pequeno.
fonte
Acabei de criar algumas estruturas abstratas chamadas fila grande e matriz grande para simplificar a tarefa de classificação e pesquisa de big data em uma única máquina com memória limitada. Basicamente, o algoritmo usado é semelhante ao que você mencionou acima - classificação de mesclagem externa.
Posso classificar dados de 128 GB (cada item 100 bytes) em 9 horas em uma única máquina e, em seguida, pesquisar binário os dados classificados quase sem tempo.
Aqui está um post sobre como pesquisar big data usando minha fila grande de código aberto e estruturas de matriz grande.
fonte