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?
Respostas:
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:
É 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:
12345
->000000012345.jpg
000000012345
->000/000/012
123
é000/000/012/00000000012345.jpg
12345678901234
da sequência, o caminho seria123/456/789/12345678901234.jpg
Algumas coisas a considerar sobre estruturas de diretório e armazenamento de arquivos:
fonte
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.
fonte
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.
fonte
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/
fonte
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á.
fonte
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 .
fonte
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.
fonte
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.
fonte
O novo MS SQL 2008 possui um novo recurso para lidar com esses casos, chamado de FILESTREAM. Dê uma olhada:
Visão geral do Microsoft TechNet FILESTREAM
fonte
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:
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.
fonte
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.
fonte
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:
Year/Month/Day/Hour_Minute_Second.png
Year/Month/Day_Hour_Minute_Second.png
etc Você entendeu meu ponto ... =)
fonte
Year/Month/Day/Hour/Minute
decidir - 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.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
fonte
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.
fonte
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.fonte
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:
Isso resultaria no caminho:
Você pode encontrar
cat.gif
na estrutura de diretórios reproduzindo o algoritmo.Usar HEX como nomes de diretório seria tão fácil quanto converter os
int
valores:Resultando em:
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!
fonte
Se você estiver no Windows, que tal um item de arquivo exFat
http://msdn.microsoft.com/en-us/library/aa914353.aspx
foi projetado com o armazenamento de arquivos de mídia em mente e está disponível agora.
fonte
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?
fonte
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.
fonte
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
000OLYMPUS
e fotos são adicionadas a essa pasta (por exemploDSC0000.RAW
). Quando o contador do nome do arquivo chega,DSC9999.RAW
uma 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 emIMG_\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.
fonte
Você pode querer dar uma olhada no ZFS (sistema de arquivos, gerenciador de volumes da Sun)
fonte
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
Armazene e carregue:
Códigos-fonte completos: https://github.com/acrobit/AcroFS
fonte
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).
fonte
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.
fonte