Armazenando um milhão de imagens no sistema de arquivos


79

Eu tenho um projeto que irá gerar um grande número de imagens. Cerca de 1.000.000 para começar. Como não são imagens grandes, armazenarei todas em uma máquina no início.

Como você recomendou o armazenamento eficiente dessas imagens? (Sistema de arquivos NTFS atualmente)

Estou pensando em um esquema de nomeação ... para iniciar, todas as imagens terão um nome incremental de 1 em diante. Espero que isso ajude a classificá-las mais tarde, se necessário, e jogá-las em pastas diferentes.

qual seria um melhor esquema de nomeação:

a / b / c / 0 ... z / z / z / 999

ou

a / b / c / 000 ... z / z / z / 999

alguma idéia sobre isso?


1
Eles estão vinculados a usuários específicos ou apenas genéricos? Eles estão agrupados de alguma maneira?

somente genérico. um monte de imagens geradas por alguns equipamentos técnicos. Estou nomeando-os incrementais de 1 para cima, apenas para ter uma idéia de uma referência de tempo.
s.mihai

como eles serão usados ​​/ acessados? através de um aplicativo sob medida ou o quê?
pomba


1
:)) sim ... 1 mil. imagens pornô :))
s.mihai

Respostas:


73

Eu recomendo usar um sistema de arquivos regular em vez de bancos de dados. Usar o sistema de arquivos é mais fácil do que um banco de dados, você pode usar ferramentas normais para acessar arquivos, os sistemas de arquivos são projetados para esse tipo de uso etc. O NTFS deve funcionar perfeitamente como um sistema de armazenamento.

Não armazene o caminho real no banco de dados. Melhor armazenar o número de sequência da imagem no banco de dados e ter uma função que possa gerar o caminho a partir do número de sequência. por exemplo:

 File path = generatePathFromSequenceNumber(sequenceNumber);

É mais fácil lidar com isso, se você precisar alterar a estrutura de diretórios de alguma forma. Talvez você precise mover as imagens para um local diferente, talvez fique sem espaço e comece a armazenar algumas das imagens no disco A e outras no disco B etc. É mais fácil alterar uma função do que alterar os caminhos no banco de dados .

Eu usaria esse tipo de algoritmo para gerar a estrutura de diretórios:

  1. Primeiro, insira o número da sequência com zeros à esquerda até ter pelo menos 12 dígitos. Este é o nome do seu arquivo. Você pode adicionar um sufixo:
    • 12345 -> 000000012345.jpg
  2. Em seguida, divida a sequência em 2 ou 3 blocos de caracteres, onde cada bloco indica um nível de diretório. Tenha um número fixo de níveis de diretório (por exemplo 3):
    • 000000012345 -> 000/000/012
  3. Armazene o arquivo no diretório sub-gerado:
    • Portanto, o caminho completo e o nome do arquivo para o arquivo com o ID da sequência 123é 000/000/012/00000000012345.jpg
    • Para arquivo com o ID 12345678901234da sequência, o caminho seria123/456/789/12345678901234.jpg

Algumas coisas a considerar sobre estruturas de diretório e armazenamento de arquivos:

  • O algoritmo acima fornece um sistema em que cada diretório folha possui no máximo 1000 arquivos (se você tiver menos do que 1 000 000 000 000 arquivos)
  • Pode haver limites de quantos arquivos e subdiretórios um diretório pode conter, por exemplo, o sistema de arquivos ext3 no Linux tem um limite de 31998 subdiretórios por um diretório.
  • As ferramentas normais (WinZip, Windows Explorer, linha de comando, shell bash, etc.) podem não funcionar muito bem se você tiver um grande número de arquivos por diretório (> 1000)
  • A própria estrutura de diretórios ocupará espaço em disco; portanto, você não precisará de muitos diretórios.
  • Com a estrutura acima, você sempre pode encontrar o caminho correto para o arquivo de imagem, apenas olhando para o nome do arquivo, se por acaso você estragar as estruturas de diretório.
  • Se você precisar acessar arquivos de várias máquinas, considere compartilhar os arquivos por meio de um sistema de arquivos de rede.
  • A estrutura de diretórios acima não funcionará se você excluir muitos arquivos. Deixa "buracos" na estrutura de diretórios. Mas como você não está excluindo nenhum arquivo, tudo deve estar bem.

1
muito interessante! dividindo o nome do arquivo ... eu não pensei nisso. Eu assumo que esta é a maneira elegante de fazê-lo: -?
217109

37
Usar um hash (como MD5) como o nome do arquivo, bem como a distribuição do diretório, funcionaria. Não apenas a integridade dos arquivos seria um benefício paralelo ao esquema de nomenclatura (facilmente verificado), mas você também terá uma distribuição razoavelmente uniforme em toda a hierarquia de diretórios. Portanto, se você tiver um arquivo chamado "f6a5b1236dbba1647257cc4646308326.jpg", você o armazenará em "/ f / 6" (ou o mais profundo que precisar). 2 níveis de profundidade fornecem 256 diretórios, ou pouco menos de 4000 arquivos por diretório, para os arquivos iniciais de 1 milhão. Também seria muito fácil automatizar a redistribuição para um esquema mais profundo.

+1 Acabei de perceber que esta resposta era semelhante à que acabei de publicar.
3dinfluence

1
Eu definitivamente concordo em usar o sistema de arquivos e criar um identificador artificial para "dividir" os nomes das pastas. Mas você também deve tentar obter uma distribuição aleatória de identificadores, ou seja, não use um número de sequência. Isso permitiria que você tivesse uma árvore de pastas mais equilibrada. Além disso, com a distribuição aleatória, você pode particionar a árvore com mais facilidade em vários sistemas de arquivos. Eu também usaria uma SAN baseada em ZFS com desduplicação ativada e um volume esparso para cada sistema de arquivos. Você ainda pode usar o NTFS usando o iSCSI para acessar a SAN.
Michael Dillon

Se você for da direita para a esquerda na etapa 2, os arquivos serão distribuídos igualmente. Além disso, você não precisa se preocupar que você não está preenchendo com zeros suficientes como você pode um número ilimitado de arquivos
Ropo

31

Vou colocar meus 2 centavos em um conselho negativo: não vá com um banco de dados.

Trabalho com bancos de dados de armazenamento de imagens há anos: arquivos grandes (1 meg-> 1 gig), frequentemente alterados, várias versões do arquivo, acessadas com bastante frequência. Os problemas de banco de dados com os quais grandes arquivos estão sendo armazenados são extremamente tediosos, os problemas de gravação e transação são complicados e você encontra problemas de bloqueio que podem causar grandes acidentes de trem. Tenho mais prática em escrever scripts dbcc e em restaurar tabelas de backups do que qualquer pessoa normal jamais deveria ter.

A maioria dos sistemas mais recentes com os quais trabalhei transferiu o armazenamento de arquivos para o sistema de arquivos e contou com os bancos de dados para nada além de indexação. Os sistemas de arquivos são projetados para aceitar esse tipo de abuso, são muito mais fáceis de expandir e você raramente perde todo o sistema de arquivos se uma entrada for corrompida.


sim. nota tomada!
s.mihai

5
Você já viu o tipo de dados FILESTREAM do SQL 2008? É um cruzamento entre o banco de dados e o armazenamento do sistema de arquivos.
NotMe

+1 na aderência ao servidor de arquivos, e não ao banco de dados, enquanto você realiza operações de E / S rápidas e pouco frequentes.

E se você estiver apenas armazenando algumas centenas de documentos ou fotos por banco de dados - alguma desvantagem de usar o banco de dados para armazenamento?
Beep beep

1
+1 ... um sistema de arquivos é uma espécie de "banco de dados" de qualquer maneira (ntfs com certeza), então por que torná-lo excessivamente complicado.
akira

12

Acho que a maioria dos sites que precisam lidar com isso usa algum tipo de hash para garantir que os arquivos sejam distribuídos igualmente nas pastas.

Então, digamos que você tenha um hash de arquivo parecido com este. 515d7eab9c29349e0cde90381ee8f810
Você pode armazená-lo no local a seguir e pode usar quantos níveis de profundidade precisar para manter o número de arquivos em cada pasta baixo.
\51\5d\7e\ab\9c\29\349e0cde90381ee8f810.jpg

Eu já vi essa abordagem várias vezes. Você ainda precisa de um banco de dados para mapear esses hashes de arquivo para um nome legível por humanos e para qualquer outro metadado que você precise armazenar. Mas essa abordagem é muito bem dimensionada porque você pode começar a distribuir o espaço de endereço de hash entre vários computadores e / ou conjuntos de armazenamento, etc.


2
Git usa uma abordagem semelhante: git-scm.com/book/en/v2/Git-Internals-Git-Objects (para fazer esta resposta up)
aexl

11

Idealmente, você deve executar alguns testes em tempos de acesso aleatório para várias estruturas, pois sua configuração específica do disco rígido, cache, memória disponível etc. podem alterar esses resultados.

Supondo que você tenha controle sobre os nomes de arquivos, eu os particionaria no nível de 1000s por diretório. Quanto mais níveis de diretório você adicionar, mais inodes serão gravados, portanto, há um push-pull aqui.

Por exemplo,

/ root / [0-99] / [0-99] / nome do arquivo

Observe que http://technet.microsoft.com/en-us/library/cc781134(WS.10).aspx possui mais detalhes sobre a instalação do NTFS. Em particular, "Se você usar um grande número de arquivos em uma pasta NTFS (300.000 ou mais), desative a geração de nomes de arquivos curtos para obter melhor desempenho e, principalmente, se os seis primeiros caracteres dos nomes de arquivos longos forem semelhantes".

Você também deve procurar desativar os recursos do sistema de arquivos que não precisa (por exemplo, hora do último acesso). http://www.pctools.com/guides/registry/detail/50/


3
+1 para desativar a geração de nome de arquivo 8.3 e a hora do último acesso; essa foi a primeira coisa que me veio à mente quando li "grande número de [arquivos]" e "NTFS" (Windows).
Rob

Link para baixo ........................
Pacerier

7

Faça o que fizer, não armazene todos em um diretório.

Dependendo da distribuição dos nomes dessas imagens, você pode criar uma estrutura de diretórios onde há pastas de nível superior com uma letra, nas quais haveria outro conjunto de subpastas para a segunda letra de imagens, etc.

Assim:

A pasta img\a\b\c\d\e\f\g\conteria as imagens começando com 'abcdefg' e assim por diante.

Você pode introduzir sua própria profundidade apropriada necessária.

O melhor dessa solução é que a estrutura de diretórios age efetivamente como um hashtable / dicionário. Dado um nome de arquivo de imagem, você saberá seu diretório e um diretório, um subconjunto de imagens que vão para lá.


\ a \ b \ c \ d \ e \ f \ eu estou fazendo agora, eu estava pensando que existe uma maneira sábia de fazer isso.
17339 s17i09

1
Essa é uma solução geralmente aceita de como armazená-los fisicamente. Gerar claramente os URLs da imagem é algo que pode ser feito dinamicamente facilmente com base no nome do arquivo de imagem. Além disso, para servi-los, você pode até introduzir subdomínios img-a, img-b no servidor de imagens, se desejar, para acelerar o tempo de carregamento.

2
E +1 em "não os armazene todos em um diretório". Estou suportando um sistema legado que colocou mais de 47000 arquivos em um servidor em uma única pasta e leva apenas um minuto para o Explorer abrir a pasta.
21810 Mark Ransom

5
Executar um \ b \ c \ d \ e \ f \ g torna a estrutura do diretório muito profunda e todo diretório contém apenas alguns arquivos. Melhor usar mais de uma letra por nível de diretório, por exemplo, ab \ cd \ ef \ ou abc \ def \. Os diretórios também ocupam espaço no disco, para que você não queira muitos deles.
Juha Syrjälä

2
Eu tinha que suportar um aplicativo que tinha mais de 4 milhões de arquivos em um diretório; funcionou surpreendentemente bem, mas você nunca conseguiu que o explorer abrisse a pasta, pois ele classificaria continuamente as novas adições. +1 para o NTFS poder lidar com isso sem morrer.
SqlACID

5

Eu os armazenaria no sistema de arquivos, mas depende de quão rápido o número de arquivos aumentará. Esses arquivos estão hospedados na web? Quantos usuários acessariam esses arquivos? Estas são as perguntas que precisam ser respondidas antes que eu possa lhe dar uma recomendação melhor. Eu também olhava para o Haystack do Facebook, eles têm uma solução muito boa para armazenar e exibir imagens.

Além disso, se você escolher o sistema de arquivos, será necessário particionar esses arquivos com diretórios. Eu estive analisando esse problema e propus uma solução, mas não é perfeita de forma alguma. Estou particionando por tabela de hash e usuários, você pode ler mais no meu blog .


as imagens não se destinam ao acesso frequente. então não há problema com isso. seu número crescerá muito rápido. Eu suponho que haverá 1mil. marca em 1 mês.
S

estou interessado na vista programador para que eu não overthink isso muito
s.mihai

Portanto, se você não precisa de acesso rápido, o Haystack provavelmente não é para você. Usar diretórios para partições é a solução mais simples na minha opinião.
Lukasz

5

Temos um sistema de armazenamento de fotos com 4 milhões de imagens. Usamos o banco de dados apenas para metadados e todas as imagens são armazenadas no sistema de arquivos usando um sistema de nomeação inversa, onde os nomes de pastas são gerados a partir do último dígito do arquivo, último-1 e assim por diante. por exemplo: 000001234.jpg é armazenado na estrutura de diretórios como 4 \ 3 \ 2 \ 1 \ 000001234.jpg.

Esse esquema funciona muito bem com o índice de identidade no banco de dados, porque preenche uniformemente toda a estrutura de diretórios.


4

Ponto rápido, você não precisa armazenar um caminho de arquivo no seu banco de dados. Você pode apenas armazenar um valor numérico, se seus arquivos forem nomeados da maneira que você descreve. Em seguida, usando um dos esquemas de armazenamento bem definidos já discutidos, você pode obter o índice como um número e encontrar rapidamente o arquivo percorrendo a estrutura de diretórios.


: -? bom ponto rápido. só que agora não tenho um algoritmo para gerar o caminho.
S05


4

Suas imagens precisarão ter um nome exclusivo? O processo que gera essas imagens pode produzir o mesmo nome de arquivo mais de uma vez? Difícil dizer sem saber qual dispositivo está criando o nome do arquivo, mas dizer que o dispositivo é 'redefinido' e, após a reinicialização, começa a nomear as imagens como na última vez em que foi 'redefinido' - se isso é uma preocupação.

Além disso, você diz que atingirá 1 milhão de imagens em um mês. Que tal depois disso? Com que rapidez essas imagens continuarão preenchendo o sistema de arquivos? Eles chegarão a algum ponto e atingirão um milhão de TOTAL de imagens ou continuarão a crescer mês após mês?

Eu pergunto porque você pode começar a projetar seu sistema de arquivos por mês e depois por imagem. Eu posso estar inclinado a sugerir que você armazene as imagens em uma estrutura de diretório:

imgs\yyyy\mm\filename.ext

where: yyyy = 4 digit year
         mm = 2 digit month

example:  D:\imgs\2009\12\aaa0001.jpg
          D:\imgs\2009\12\aaa0002.jpg
          D:\imgs\2009\12\aaa0003.jpg
          D:\imgs\2009\12\aaa0004.jpg
                   |
          D:\imgs\2009\12\zzz9982.jpg
          D:\imgs\2010\01\aaa0001.jpg (this is why I ask about uniqueness)
          D:\imgs\2010\01\aab0001.jpg

Mês, ano e até dia são bons para imagens do tipo segurança. Não tenho certeza se é isso que você está fazendo, mas eu fiz isso com uma câmera de segurança doméstica que tirava uma foto a cada 10 segundos ... Dessa forma, seu aplicativo pode detalhar o horário específico ou até um intervalo em que você imagina que a imagem foi gerada . Ou, em vez de ano, mês - existe algum outro "significado" que pode ser derivado do próprio arquivo de imagem? Alguns outros descritores, além do exemplo de data que dei?

Eu não armazenaria os dados binários no banco de dados. Nunca tive um bom desempenho / sorte com esse tipo de coisa. Não consigo imaginá-lo funcionando bem com 1 milhão de imagens. Gostaria de armazenar o nome do arquivo e é isso. Se todos eles serão JPG, nem armazene a extensão. Eu criaria uma tabela de controle que armazenasse um ponteiro no servidor, na unidade, no caminho do arquivo, etc. Dessa forma, você pode mover essas imagens para outra caixa e ainda localizá-las. Você precisa marcar as suas imagens com palavras-chave? Nesse caso, você deseja criar as tabelas apropriadas que permitem esse tipo de marcação.

Você / outras pessoas podem ter abordado essas idéias enquanto eu respondia. Espero que isso ajude.


1. todos os arquivos serão nomeados com exclusividade 2. o sistema crescerá e crescerá primeiro, exibirá imagens de 1 milhão e depois crescerá a uma taxa de algumas dezenas de milhares por mês. 3. haverá algum tipo de marcação dos arquivos em algum momento no futuro, é por isso que eu quero armazenar algum tipo de dados de identificação no banco de dados.
s.mihai

3

Estou envolvido em um projeto que armazena 8,4 milhões de imagens no decorrer de um ano para documentar o status de vários dispositivos. Imagens mais recentes são acessadas com mais frequência, e imagens mais antigas raramente são procuradas, a menos que uma condição seja descoberta, o que leva alguém a procurar nos arquivos.

Minha solução, com base nesse uso, foi compactar gradualmente as imagens em arquivos compactados. As imagens são JPGs, cada uma com aproximadamente 20kB e não compactam muito; portanto, o esquema de compactação ZIP é inexistente. Isso é feito apenas para concatená-los em uma entrada do sistema de arquivos, o que ajuda muito o NTFS em termos de velocidade quando se trata de movê-los de uma unidade para outra, ou de pesquisar na lista de arquivos.

Imagens com mais de um dia são combinadas em um zip "diário"; os zíperes com mais de um mês são combinados no respectivo zip "mensal"; e, finalmente, qualquer coisa durante um ano não é mais necessária e, consequentemente, excluída.

Esse sistema funciona bem porque os usuários podem procurar os arquivos (por meio do sistema operacional ou de vários aplicativos clientes) e tudo é nomeado com base nos nomes dos dispositivos e nos registros de data e hora. Geralmente, um usuário conhece essas duas informações e pode localizar rapidamente qualquer um dos milhões de imagens.

Entendo que isso provavelmente não esteja relacionado aos seus detalhes específicos, mas pensei em compartilhar.


2

Talvez um esquema de nomenclatura baseado na data de criação - incluindo todas as informações no nome do arquivo ou (melhor para navegar mais tarde) dividindo-as em diretórios. Posso pensar no seguinte, dependendo da frequência com que você gera imagens:

  • Várias imagens geradas a cada dia: Year/Month/Day/Hour_Minute_Second.png
  • Um par por mês: Year/Month/Day_Hour_Minute_Second.png

etc Você entendeu meu ponto ... =)


eles não são continuamente gerados ao longo do tempo, de modo que algumas pastas vai se tornar gordura e outros ficam ... fino :))
s.mihai

Bem, obviamente você não precisa criar cada pasta, apenas porque está seguindo este esquema. Você pode até Year/Month/Day/Hour/Minutedecidir - quantos níveis de pastas você precisa, dependendo da frequência com que as imagens são geradas quando a taxa é mais alta - e simplesmente não criar pastas que ficariam vazias.
Tomas Aschan

2

Eu estaria inclinado a criar uma estrutura de pastas baseada em data, por exemplo, \ ano \ mês \ dia, e usar carimbos de data e hora para os nomes de arquivos. Se necessário, os carimbos de data e hora podem ter um componente de contador adicional se as imagens forem criadas com tanta rapidez que pode haver mais de um dentro de um milissegundo. Usando uma sequência mais significativa para menos significativa para a classificação de nomes, a localização e a manutenção são fáceis. por exemplo, hhmmssmm [seq] .jpg


2

Você está considerando a recuperação de desastres?

Algumas das soluções propostas aqui acabam manipulando o nome do arquivo (de modo que, se o arquivo físico fosse movido, você perderia o controle de qual arquivo é realmente). Eu recomendo manter um nome de arquivo físico exclusivo para que, se sua lista principal de locais de arquivos for corrompida, você possa regenerá-lo com um pequeno shell, er, powershell, script;)

Pelo que li aqui, parece que todos esses arquivos seriam armazenados em um sistema de arquivos. Considere armazená-los em vários sistemas de arquivos em várias máquinas. Se você tiver os recursos, determine um sistema para armazenar cada arquivo em duas máquinas diferentes, caso você perca uma fonte de alimentação e a substituição seja daqui a 2 dias.

Considere que tipos de procedimentos você precisaria criar para migrar arquivos entre máquinas ou sistemas de arquivos. A capacidade de fazer isso com o sistema é ativa e on-line pode economizar uma dor de cabeça considerável no caminho.

Você pode considerar usar um GUID como um nome de arquivo físico, em vez de um número incremental, caso seu contador de números incrementais (a coluna de identidade do banco de dados?) Fique bagunçado.

Se apropriado, considere usar uma CDN como o Amazon S3.


2

Embora eu não tenha exibido fotos nessa escala, escrevi anteriormente um pequeno aplicativo de galeria para exibir ~ 25k fotos em uma máquina de 400 MHz w. 512 MB de RAM ou mais. Algumas experiências;

  • Evite bancos de dados relacionais a todo custo; embora os bancos de dados, sem dúvida, sejam inteligentes no manuseio de dados, eles não foram projetados para esse uso (temos bancos de dados hierárquicos especializados de valores-chave para os chamados sistemas de arquivos ). Embora eu não tenha nada além de um palpite, aposto que o cache do banco de dados sai pela janela, se você atirar grandes bolhas nele. Enquanto meu hardware disponível era pequeno, não tocar no banco de dados na pesquisa de imagens dava ordens de magnitude a uma velocidade melhor.

  • Pesquise como o sistema de arquivos se comporta; no ext3 (ou era ext2 na época - não me lembro), o limite de poder procurar com eficiência subdiretórios e arquivos estava em torno da marca 256; portanto, tendo apenas muitos arquivos e pastas em qualquer pasta. Mais uma vez, aumento notável. Embora eu não conheça o NTFS, coisas como o XFS (que usa árvores B, pelo que me lembro) são extremamente rápidas, simplesmente porque elas podem fazer pesquisas extremamente rápidas.

  • Distribua dados uniformemente; quando experimentei o acima, tentei distribuir os dados uniformemente por todos os diretórios (fiz um MD5 da URL e o usei para diretórios; /1a/2b/1a2b...f.jpg). Dessa forma, leva mais tempo para atingir qualquer limite de desempenho existente (e o cache do sistema de arquivos é nulo em conjuntos de dados tão grandes). (por outro lado, convém ver onde estão os limites desde o início; depois, jogue tudo no primeiro diretório disponível.


2

Pode ser tarde para o jogo sobre isso. Mas uma solução (se for o caso de uso) pode ser o hash do nome do arquivo. É uma maneira de criar um caminho de arquivo facilmente reproduzível usando o nome do arquivo, além de criar uma estrutura de diretórios bem distribuída. Por exemplo, você pode usar os bytes do hashcode do nome do arquivo como caminho:

String fileName = "cat.gif";
int hash = fileName.hashCode();
int mask = 255;
int firstDir = hash & mask;
int secondDir = (hash >> 8) & mask;

Isso resultaria no caminho:

/172/029/cat.gif

Você pode encontrar cat.gifna estrutura de diretórios reproduzindo o algoritmo.

Usar HEX como nomes de diretório seria tão fácil quanto converter os intvalores:

String path = new StringBuilder(File.separator)
        .append(String.format("%02x", firstDir))
        .append(File.separator)
        .append(String.format("%02x", secondDir)
        .toString();

Resultando em:

/AC/1D/cat.gif

Escrevi um artigo sobre isso há alguns anos e recentemente o mudei para o Medium. Ele tem mais alguns detalhes e algum código de exemplo: Hashing de nome de arquivo: Criando uma estrutura de diretório com hash . Espero que isto ajude!


Armazenamos 1,8 bilhão de itens usando algo semelhante. Isso funciona bem. Use um hash rápido, com baixas taxas de colisões e pronto.
CVVS 02/04/19


1

Se TODOS eles não são imediatamente necessários e você pode gerá-los on-the-fly e essas são pequenas imagens, por que não implementar um cache de memória ou disco LRU acima do seu gerador de imagens?

Isso poderia poupar você do armazenamento e manter as imagens quentes a serem exibidas do mem?


1

Acabei de executar um teste no zfs porque amo o zfs e tinha uma partição 500gig na qual eu tinha compressão. Eu escrevi um script que gerava 50-100k arquivos e os colocava em diretórios aninhados 1/2/3/4/5/6/7/8 (5-8 níveis de profundidade) e deixei que funcionasse por 1 semana. (não era um ótimo script.) Encheu o disco e acabou tendo cerca de 25 milhões de arquivos. O acesso a qualquer arquivo com um caminho conhecido foi instantâneo. A listagem de qualquer diretório com um caminho conhecido foi instantânea.

Obter uma contagem da lista de arquivos, no entanto (via localização), levou 68 horas.

Também realizei um teste colocando muitos arquivos em um diretório. Eu consegui cerca de 3,7 milhões de arquivos em um diretório antes de parar. A listagem do diretório para obter uma contagem levou cerca de 5 minutos. A exclusão de todos os arquivos nesse diretório levou 20 horas. Mas a pesquisa e o acesso a qualquer arquivo foram instantâneos.


1

Vejo outra referência a um banco de dados, mas não vejo menção a isso em sua postagem. De qualquer forma, minha opinião sobre esse ponto em particular é: fique com um banco de dados ou com um sistema de arquivos. Se você precisar misturar os dois, tenha cuidado. As coisas ficam mais complicadas. Mas você pode precisar. Armazenar um milhão de fotos em um banco de dados não parece a melhor idéia.

Você pode estar interessado pela seguinte especificação, a maioria das câmeras digitais segui-lo para gerenciar o armazenamento de arquivos: https://en.wikipedia.org/wiki/Camera_Image_File_Format

Essencialmente, uma pasta é criada, como 000OLYMPUSe fotos são adicionadas a essa pasta (por exemplo DSC0000.RAW). Quando o contador do nome do arquivo chega, DSC9999.RAWuma nova pasta é criada ( 001OLYMPUS) e a imagem é adicionada novamente, redefinindo o contador, possivelmente com um prefixo diferente (ex:) P_0000.RAW.

Como alternativa, você também pode criar pastas com base em partes do nome do arquivo (já mencionado várias vezes). Por exemplo, se sua foto tiver o nome IMG_A83743.JPG, armazene-a em IMG_\A8\3\IMG_A83743.JPG. É mais complicado de implementar, mas facilitará a localização de seus arquivos.

Dependendo do sistema de arquivos (isso exigirá alguma pesquisa), você poderá despejar todas as imagens em uma única pasta, mas, na minha experiência, isso normalmente causaria problemas de desempenho.


0

Você pode querer dar uma olhada no ZFS (sistema de arquivos, gerenciador de volumes da Sun)


0

Uma maneira limpa de gerar o caminho a partir de um grande número é convertê-lo facilmente em hexadecimal e depois dividi-lo!

por exemplo 1099496034834> 0xFFFF1212>FF/FF/12/12

public string GeneratePath(long val)
{  
    string hex = val.ToString("X");
    hex=hex.PadLeft(10, '0');
    string path="";
    for(int i=0; i<hex.Length; i+=2 )
    {
        path += hex.Substring(i,2);
        if(i+2<hex.Length)
            path+="/";
    }
    return path;
}

Armazene e carregue:

public long Store(Stream doc)
{
   var newId = getNewId();
   var fullpath = GeneratePath(newId)
   // store into fullpath 
   return newId;
}

public Stream Load(long id)
{
   var fullpath = GeneratePath(newId)
   var stream = ... 
   return stream;
}

Códigos-fonte completos: https://github.com/acrobit/AcroFS


-1

Infelizmente, os sistemas de arquivos são muito ruins (desempenho com muitos arquivos por diretório ou árvores de diretório profundas, verificação de tempos de reinicialização, confiabilidade) ao gerenciar muitos arquivos pequenos, portanto a solução acima que envolve arquivos ZIP é melhor se você deseja usar um sistema de arquivos.

Usar um gerenciador de banco de dados é de longe a melhor opção; um simples como BDB ou GDBM, por exemplo; mesmo um DBMS relacional como o MySQL seria melhor. Somente pessoas preguiçosas que não entendem sistemas de arquivos e bancos de dados (por exemplo, aqueles que descartam transações) tendem a usar sistemas de arquivos como bancos de dados (ou um pouco mais raramente, vice-versa).


-2

Que tal um banco de dados com uma tabela contendo um ID e um BLOB para armazenar a imagem? Em seguida, você pode adicionar novas tabelas sempre que desejar associar mais elementos de dados a uma foto.

Se você está esperando escalar, por que não escalar agora? Você economizará tempo agora e mais tarde na IMO. Implemente a camada de banco de dados uma vez, o que é bastante fácil para começar. Ou implemente algo com pastas e nomes de arquivos e blá blá blá e depois mude para outra coisa quando começar a explodir MAX_PATH.


5
Estive lá, fiz isso, tenho as cicatrizes para provar isso. Os bancos de dados que armazenam imagens em grandes números são irritadiços, quase irreconhecíveis e requerem quantidades excessivas de manutenção. Muito melhor para armazená-los no sistema de arquivos a menos que você tenha uma necessidade específica que só pode ser respondida por um banco de dados (o nosso era rastreamento versão.)
Satanicpuppy

1
E existem muitos utilitários para lidar com arquivos e sistemas de arquivos, poucos ou nenhum para lidar com arquivos em um banco de dados.
Mark Ransom

2
Oh Deus Não. Por favor, não use um banco de dados como um grande armazenamento BLOB.
187 Neil N

Eek. Não sabia que os bancos de dados (ainda?) Têm tantos problemas com BLOBs.

Como uma solução tão ruim que tem tantos comentários ainda pode ter um +1? nenhuma ofensa ao OP (eu vejo que veio do SO), mas o botão de voto negativo está aqui por uma razão!
Mark Henderson
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.