Ordenar algoritmos que funcionam com grande quantidade de dados


12

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.


1
Que tipo de dados? Conjuntos de dados diferentes podem significar algoritmos diferentes que melhor atendem ao seu objetivo.
Whatsisname

É um arquivo de texto e eu tenho que ordenar as linhas. As linhas não têm comprimento fixo, mas o comprimento não varia muito (cerca de 50 caracteres por registro).
Giorgio

3
Não conheço seu ambiente ou suas restrições, mas usaria um banco de dados para classificar sempre que possível. Isso ocorre porque é quase 100% à prova de erros e será muito mais eficiente que o meu código.
NoChance

Estou trabalhando no Linux / Java. Eu implementei a classificação por mesclagem e parece funcionar de maneira bastante suave. Classificar vários milhões de linhas leva algum tempo, mas eu só preciso fazer isso de vez em quando.
Giorgio

@Giorgio, é bom que você tenha implementado esse algoritmo. Para o trabalho de produção, ainda sugiro que você use um banco de dados. Não apenas pela velocidade, mas também pela confiabilidade e facilidade de manutenção.
precisa saber é o seguinte

Respostas:


13

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.


2
Obrigado pela referência: tenho quase certeza de que encontrarei material interessante no livro de Knuth. Não tenho certeza de que as técnicas de classificação de falta de memória não sejam relevantes hoje. Talvez não seja para tarefas comuns do dia-a-dia, mas posso imaginar que ainda há muitas situações em que conjuntos de dados muito grandes precisam ser processados.
Giorgio

Os algoritmos de Knuth são sempre úteis. Por exemplo, uma classificação mesclada com um buffer de classificação heap pode ser muito eficaz e MUITO fácil de implementar.
Sulthan

4
Não é uma resposta muito útil porque o material referido não é gratuito. Para o OP, sugiro pesquisar no Google por uma resposta. Você não precisa gastar US $ 50 dólares para obter um livro quando encontrar esse tipo de informação pesquisando na web. Obviamente, você também pode fazer o download gratuito de alguns sites ( ahem ). Dificilmente merecedor de uma resposta aceita.
Thomas Eding

1
@ThomasEding, existem algumas coisas chamadas "bibliotecas" que contêm grandes quantidades desses dispositivos obsoletos de armazenamento e recuperação de informações chamados "livros". "Bibliotecas" disponibilizam "livros" GRATUITAMENTE. Se a sua "biblioteca" específica não possui o "livro" específico que você procura, eles também oferecem um serviço GRATUITO chamado "empréstimo entre bibliotecas", que permite à "biblioteca" emprestar o "livro" de outra "biblioteca", para que eles possam empreste para você.
John R. Strohm

6

A mesclagem externa do R-Way, como no sortcomando 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.


Obrigado. A fusão externa do R-Way parece diferente do que eu tinha em mente. Leitura interessante.
Giorgio

4

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:

  • Arquivo no local ou vários arquivos?
  • Uma vez, periódico ou mantê-lo sempre organizado?
  • Quanto maior que a memória (quantas cargas de memória passam por todo o conjunto de dados)?
  • Está em um banco de dados? Pode ser?
  • Você controla o código que lê os dados ou outras pessoas estão descartando um arquivo diretamente?
  • Formato de arquivo? (Texto? Registro fixo?)
  • Alguma outra circunstância especial sobre a qual não perguntei?

Obrigado pela resposta. O que você quer dizer com "Registro no local ou múltiplo"?
Giorgio

Desculpe, deveria ter revisado minha resposta - eu quis dizer vários arquivos. No local, praticamente implica tamanhos de registros fixos e indexação; nesse momento, você provavelmente desejaria um banco de dados.
Bill K

Não, não está no lugar: os registros não têm tamanho fixo. Eu uso quatro arquivos temporários para minha implementação atual.
Giorgio

Você pode interpretar a saída com código ou precisa estar em um formato específico (arquivo de texto simples?) Com que frequência precisa ser classificada - toda vez que algo é adicionado ou apenas ocasionalmente? Quando algo é adicionado, é apenas anexado ao final ou você pode escrever o código que o adiciona?
Bill K

Cada linha pode ser analisada em um registro (o arquivo é um arquivo CSV), mas a maioria dos campos é de texto. Ele precisa ser classificado de vez em quando (por exemplo, todos os meses) e leva cerca de 1 hora para classificar com minha implementação atual. Para inserir uma linha, eu poderia escrever o código que a insere no lugar certo: com o código que tenho até agora, levaria 20 minutos para escrever essa ferramenta.
Giorgio

3

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 .


1
+1: link interessante. A mesclagem não é um exemplo de mapa / redução, onde o mapa corresponde às sub-listas de classificação e reduzir corresponde à mesclagem?
Giorgio1

Pode ser visto assim, mas você pode usar o Hadoop para fazer isso por você, em vez de escrever você mesmo.
M3th0dman

1

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.


0

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.

  1. De alguma forma, peça seu "banco de dados"
  2. Atribua um número inteiro a cada entrada (1, 2, 3, 4, ..., n) (melhor: use alguns índices esparsos)
  3. Ao adicionar um incremento, encontre uma lacuna onde o número esquerdo seja menor ou igual e o número certo seja maior ou igual (não deve ser difícil com alguma versão modificada de uma pesquisa binária)
  4. Insira, enquanto as lacunas são suficientemente grandes, se não: apenas reindexe (nunca classifique novamente) :-)

0

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.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.