Ir para o conteúdo

Publicidade

 Estatísticas do Fórum

  • 0 Usuários ativos

    0 membro(s), 0 visitante(s) e 0 membros anônimo(s)

Cursos Online iMasters
Foto:

[Resolvido] Armazenar imagens em banco de dados ou diretórios?

  • Por favor, faça o login para responder
27 respostas neste tópico

#1 Tiago Souza Ribeiro

Tiago Souza Ribeiro

    π 8 π

  • Membros
  • 252 posts

Postado 17 julho 2012 - 02:30

Olá, minha dúvida agora é coisa simples: meu site que estou fazendo terá um sistema de uploads de imagens e eu gostaria de saber, qual o melhor método para armazenar estas imagens?
- Armazenar normalmente em diretórios
- Codificar em URI Base64 e salvar em banco de dados MySQL
Qual método me recomendam? Qual a vantagem do mesmo sobre o outro?

Até mais. :D

Editado por Tiago Souza Ribeiro, 17 julho 2012 - 02:30 .

  • 0

#2 lightfox

lightfox
  • Membros
  • 148 posts

Postado 17 julho 2012 - 02:39

envie o nome da imagem para o banco de dados.
exemplo de um script que eu tenho aqui:


function trocar_acentos ($imagem)
{
		$imagem = str_replace(' ','_',$imagem);
		$imagem = str_replace('á','a',$imagem);
		$imagem = str_replace('ã','a',$imagem);
		$imagem = str_replace('â','a',$imagem);
		$imagem = str_replace('ä','a',$imagem);
		$imagem = str_replace('à','a',$imagem);
		$imagem = str_replace('Á','a',$imagem);
		$imagem = str_replace('À','a',$imagem);
		$imagem = str_replace('Ã','a',$imagem);
		$imagem = str_replace('Â','a',$imagem);
		$imagem = str_replace('Ä','a',$imagem);
		$imagem = str_replace('ç','c',$imagem);
		$imagem = str_replace('Ç','c',$imagem);
		$imagem = str_replace('é','e',$imagem);
		$imagem = str_replace('É','e',$imagem);
		$imagem = str_replace('í','i',$imagem);
		$imagem = str_replace('Í','i',$imagem);
		$imagem = str_replace('ó','o',$imagem);
		$imagem = str_replace('Ó','o',$imagem);
		$imagem = str_replace('ú','u',$imagem);
		$imagem = str_replace('Ú','u',$imagem);
		$imagem = strtolower($imagem);

		return $imagem;
}



$imagem = trocar_acentos ($_FILES['imagem']['name']);
$imagem_extensao = substr($imagem,strpos($imagem,'.')+1,strlen($imagem)-strpos($imagem,'.'));
$imagem_tamanho = $_FILES['imagem']['size'];
$imagem_descricao = $_POST['imagem_descricao'];
$imagem_data = date_default_timezone_set('America/Sao_Paulo');


		$uploaddir = "/uploads/";
		$data = time();
		
        if ($imagem != ""){
		if (file_exists($uploaddir.$imagem))
		{
			$imagem = $data."_".$imagem;
		}
		}



move_uploaded_file($_FILES['imagem']['tmp_name'], $uploaddir . $imagem);

$query = "insert into uploads (imagem) values ('$imagem')";
$rs = mysql_query($query);


precisa ser aprimorado, mas ja da pra começar :)
qualquer modificação poste ai :D

Editado por lightfox, 17 julho 2012 - 02:41 .

  • 0

#3 mangakah

mangakah

    "L"

  • Membros
  • 1.856 posts

Postado 17 julho 2012 - 02:49

Armazenar os arquivos em um diretório e apenas o nome do arquivo no banco de dados é a melhor opção.

A outra opção tem as seguintes desvantagens:
  • Codificar em Base64 deixa a string maior.
  • Requer cuidados com a codificação dos dados (se não for usar Base64).
  • Se der algum problema na tabela (corrupção de dados, por exemplo), além de perder todos os dados, você perderá também os arquivos.
  • Consome mais recursos do servidor (bem... eu nunca testei e comparei, mas acredito que seja verdade).

Como diriam os Titãs: o fácil é o certo. A solução mais simples é sempre a melhor.
  • 0

#4 Tiago Souza Ribeiro

Tiago Souza Ribeiro

    π 8 π

  • Membros
  • 252 posts

Postado 17 julho 2012 - 03:05

A seguir, uma lista de vantagens e desvantagens que elaborei de cada método.

Vantagens do método Base64:
- Muito mais fácil de armazenar
- Carregamento mais rápido por fugir do limite de conexões por host
- Posso impedir por PHP o uso de imagens específicas em outros sites

Vantagens do método tradicional:
- Não faz query's ao banco de dados
- É indexada pelo Google
- Menos chances de perda total
- Menor uso do disco

Desvantagens do método Base64:
- Faz mais query's ao banco de dados
- O tamanho da tabela será enorme se houver muitas imagens
- Não sei se será indexada pelo Google

Desvantagens do método tradicional:
- Pode-se ser usada em outros sites, sem permissão...
- Se for bloquear o uso em outros sites, por htaccess, vai bloquear todas por extensão, ou terá que modificar sempre o arquivo para incluir novas imagens separadamente

Então, analisando isso ae, qual é realmente vantajoso? Fiquei confuso, e podem haver outras vantagens/desvantagens que deixei passar.
  • 0

#5 mangakah

mangakah

    "L"

  • Membros
  • 1.856 posts

Postado 17 julho 2012 - 03:29

É muito fácil impedir o hotlinking de suas imagens através do htaccess.

Exemplo:
 RewriteEngine on
 RewriteCond %{HTTP_REFERER}     !^$
 RewriteCond %{REQUEST_FILENAME} -f
 RewriteCond %{REQUEST_FILENAME} \.(gif|jpe?g?|png)$           [NC]
 RewriteCond %{HTTP_REFERER}     !^https?://([^.]+\.)?seu-dominio\.com\.br [NC]
 RewriteRule \.(gif|jpe?g?|png)$

  • 1

#6 Tiago Souza Ribeiro

Tiago Souza Ribeiro

    π 8 π

  • Membros
  • 252 posts

Postado 17 julho 2012 - 04:15

Pois é, mas desse jeito ae, vou estar impedindo de todas imagens ao mesmo tempo. E se eu quiser bloquear apenas algumas? Não posso ficar editando htaccess direto, tem que ser tudo automático.
Ah, aproveitando que tamo falando de hotlink (que nem é bem o foco do tópico): se eu bloquear, vai impedir indexação pelo Google por exemplo?

Editado por Tiago Souza Ribeiro, 17 julho 2012 - 04:16 .

  • 0

#7 mangakah

mangakah

    "L"

  • Membros
  • 1.856 posts

Postado 17 julho 2012 - 04:55

Pois é, mas desse jeito ae, vou estar impedindo de todas imagens ao mesmo tempo. E se eu quiser bloquear apenas algumas? Não posso ficar editando htaccess direto, tem que ser tudo automático.


É só redirecionar para um arquivo PHP então...
 # As primeiras três linhas do meu exemplo anterior aqui...
 RewriteCond %{REQUEST_FILENAME} /([A-Z0-9\-_])\.(gif|jpe?g|png)$ [NC]
 RewriteCond %{HTTP_REFERER}     !^https?://(?:[^.]+\.)?seu-dominio\.com\.br [NC]
 RewriteRule . imagem.php?filename=%1&extension=%2


Ah, aproveitando que tamo falando de hotlink (que nem é bem o foco do tópico): se eu bloquear, vai impedir indexação pelo Google por exemplo?


Bom... você que falou que só era possível ter controle sobre o acesso a image e impedir que outros usem sem permissão só seria possível se a imagem estivesse no banco de dados. Eu discordo. Existem muitas maneiras de prevenir hotlinking de imagens armazenadas no sistema de arquivos. Obviamente que sempre é possível burlar essas proteções, mas essa burla também vale para o armazenamento da imagem no banco de dados.

Creio que irá acontecer o seguinte: o Google irá criar o thumbnail da imagem e indexar normalmente, mas quando a imagem aparecer nos resultados de uma busca e o usuário clicar nela ele receberá um erro 404 ou um erro forbidden ou o que mais você programar para quando alguém tentar fazer hotlinking com a sua imagem. Já me aconteceu isso algumas vezes... é frustrante e faz o usuário perder tempo, portanto, se você for fazer isso, é melhor já bloquear logo o Googlebot-Images no seu robots.txt.
  • 1

#8 Tiago Souza Ribeiro

Tiago Souza Ribeiro

    π 8 π

  • Membros
  • 252 posts

Postado 17 julho 2012 - 17:39

Não acho que vai dar erro 404, já que o link vai apontar para a imagem original, no meu site mesmo, ela não vai estar em outro site, então não será hotlinking...

Sobre a hospedagem ae: eu acho que vou armazenar no banco de dados somente imagens que poderão ser alteradas a qualquer momento, ex: o avatar de um usuário, ele pode mudar a qualquer momento, e acho que seria mais fácil só alterar o Base64 da imagem no banco de dados, do que deletar a imagem atual no disco, e colocar a nova no lugar.... Imagens fixas, do layout, postagens, etc... vou armazenar no método tradicional mesmo, já que serão fixas, não serão alteradas, não por outras pessoas.

Vlw ae :D
  • 0

#9 Evandro Oliveira

Evandro Oliveira

    leia ali -->

  • Membros
  • 4.540 posts

Postado 17 julho 2012 - 18:53

Spoiler



O cara nem leu a pergunta...

Em MySQL, desencana. Local físico, no banco você guarda só o caminho. Se for guardar o conteúdo das imagens em banco, sugiro Postgres ou alugm NoSQL como MongoDB.
  • 0

#10 Andrey Knupp Vital

Andrey Knupp Vital

    Web Developer

  • Moderadores
  • 4.434 posts

Postado 17 julho 2012 - 19:01

No MySQL, desencana mesmo, alias, eu sou totalmente contra gravar imagens em um banco de dados, por N motivos, eu prefiro deixar no FS.
Eu só guardaria imagens no banco, se por algum motivo em especial eu não tiver permissão de escrita em um diretório de armazenamento (talvez nunca aconteça, mas ...), no banco é totalmente inviável porque:

Se você possui select com relacionamentos, e alteração dinâmica na tabela, ou um acesso concorrente significante, você vai ter um trafego muito grande, e suas consultas podem demorar.

Pensando em 10.000 registros, você já começaria com alguns problemas, e claro sem falar no tamanho do buffer de saída na página, que ia ficar ENORME dependendo da quantidade de registros.

Outra que o propósito do banco não é bem esse, os campos BLOB, LONGBLOB, podem ser usados para esse caso, mas iria cair na mesma questão das queries, vai ser lento, e eu sinceramente acho, que isso é um erro de modelagem.

Editado por Andrey Knupp, 17 julho 2012 - 19:15 .

  • 0

#11 Tiago Souza Ribeiro

Tiago Souza Ribeiro

    π 8 π

  • Membros
  • 252 posts

Postado 17 julho 2012 - 21:58

Obrigado a todos pelas respostas.
Bom, eu apenas pensei em salvar o conteúdo da imagem no banco de dados por ser muito mais fácil... eu apenas codificaria ele em base64 e pronto, salvaria no db, porém notei que assim usa 33% a mais de espaço em disco, segundo a página da função base64_encode no php.net.
Olhando o script do lightfox dei uma pesquisada sobre a variável $_FILES e a função move_uploaded_file e deu pra entender como fazer o upload normal, eu nunca precisei usar isso, então achei que era mais complicado, kkk.
Então, vou usar o método normal mesmo, até porque vocês crucificaram ae o outro, hehe.
Só mais uma coisa: o Evandro falou ae que seria melhor no Postgree ou algum NoSQL... porque eles sim, e o MySQL não? MySQL só serve para pequenas strings? Se for, vou ter que migrar para Postgree... estava pretendendo salvar o código fonte das postagens no banco de dados, e isso poderia ser bem grande...
  • 0

#12 Evandro Oliveira

Evandro Oliveira

    leia ali -->

  • Membros
  • 4.540 posts

Postado 18 julho 2012 - 00:43

Obrigado a todos pelas respostas.
Bom, eu apenas pensei em salvar o conteúdo da imagem no banco de dados por ser muito mais fácil... eu apenas codificaria ele em base64 e pronto, salvaria no db, porém notei que assim usa 33% a mais de espaço em disco, segundo a página da função base64_encode no php.net.
Olhando o script do lightfox dei uma pesquisada sobre a variável $_FILES e a função move_uploaded_file e deu pra entender como fazer o upload normal, eu nunca precisei usar isso, então achei que era mais complicado, kkk.
Então, vou usar o método normal mesmo, até porque vocês crucificaram ae o outro, hehe.
Só mais uma coisa: o Evandro falou ae que seria melhor no Postgree ou algum NoSQL... porque eles sim, e o MySQL não? MySQL só serve para pequenas strings? Se for, vou ter que migrar para Postgree... estava pretendendo salvar o código fonte das postagens no banco de dados, e isso poderia ser bem grande...


A questão não é bem o tamanho e sim o tipo. MySQL é ótimo e muito performático armazenando longas cadeias de caracteres. Mas estamos falando de texto plano. Postgres cairia no mesmo problema, a ressalva é que a gestão de conteúdo binário nos campos *BLOB é otimizada neste banco.

NoSQL já é um outro ecossistema. Não sei nem porque cismam em querer comparar com SGDB's relacionais.
  • 0

#13 Andrey Knupp Vital

Andrey Knupp Vital

    Web Developer

  • Moderadores
  • 4.434 posts

Postado 18 julho 2012 - 10:43

@Evandro Oliveira, independente disso kra, eu acho errado.
Me diz um motivo pra gravar imagens no banco de dados.

Editado por Andrey Knupp, 18 julho 2012 - 10:43 .

  • 0

#14 Evandro Oliveira

Evandro Oliveira

    leia ali -->

  • Membros
  • 4.540 posts

Postado 18 julho 2012 - 10:57

@Evandro Oliveira, independente disso kra, eu acho errado.
Me diz um motivo pra gravar imagens no banco de dados.


Acesso, minimização de leitura, menos requisições de memória, apenas um ponteiro, menos recursos de processamento.

Imagine que o disco é um grande - enorme - corredor contendo arquivos. Seu diretório /images fica no começo desse corredor. Em um gaveta, em um dos primeiros arquivos.

Seu banco de dados, armazena o conteúdo - índices, tabelas, valores - lá pelo meio/final do corredor. Quem espera esses dados, te espera depois do final do corredor.

Você vai até o meio, para procurar em algum registro onde se encontra a imagem física, descobre, volta até o começo, pega a imagem e leva até o fim do corredor.

Veja: busca -> leitura -> envio -> busca -> envio

Armazenando tudo em um único local, podemos trabalhar um único sistema de caching, otimizar um único "sistema de arquivos" e fazer apenas um acesso ao disco

busca -> envio
  • 0

#15 Andrey Knupp Vital

Andrey Knupp Vital

    Web Developer

  • Moderadores
  • 4.434 posts

Postado 18 julho 2012 - 12:04

Certo, agora um bench que eu fiz:
<?php
       $m = new Mongo();
       $db = $m->bench ;
       /*$content = file_get_contents('jQuery.jpg');
       $content = base64_encode($content);

       for($i = 0 ; $i < 1000 ; ++$i){
            $db->images->insert(array(
                "i" => $i,
                "contentEncoded" => $content
            ));
       }*/

       $s = microtime(true);
       foreach($db->images->find() as $image){
          var_dump($image);
       }
       $e = (microtime(true) - $s);
       var_dump($e);

Inseri, depois comentei o código, e fiz a leitura ...
float(70.329179048538)

Esse resultado para 1000 copias de uma imagem de 128KB (nem todas terão 128KB, talvez você faça resize, talvez guarde a original e o thumb).
Daí depois tenta apertar CTRL+U.

Não vale apena ... sinceramente, você gasta alguns segundos levando em consideração o que o Evandro falou, é mais em conta do que gravar isso no banco (eu acho).
Se quiser fazer o bench sem usar o DB, simples, pega uma imagem de 128KB codifica o base 64, depois faz o looping exibindo o conteúdo..
<?php
       $content = file_get_contents('jQuery.jpg');
       $content = base64_encode($content);

       $s = microtime(true);
       for($i = 0; $i < 1000; ++$i){
            echo $content ;
       }
       $e = (microtime(true) - $s);
       var_dump($e);

Informe o resultado e o que você acha.
E ainda leva em consideração o tamanho do trafego de dados entre o servidor php e o banco de dados.
E lembre da concorrência, suponha uns 20 - 30 usuários, claro que você não vai trazer 1000 imagens, pode limitar sua busca a 10 (talvez uma lista), ou coisa assim.

Para testar a concorrência, pode usar o apache benchmark.
Não dá pra fazer todos esses testes agora, mas....

Lembrando também, que isso também vai aumentar o tamanho do arquivo (caso o armazenamento das imagens for no banco), e como você citou um "caching", se você guarda por 5 minutos, e exibe pra 30 usuários, você vai ler um arquivo de no mínimo 3-4 MB a cada requisição.

E provavelmente, qualquer consulta a nodes do documento com jQuery, ou JS Puro, irá demorar (não tenho crtz, não fiz o teste)

@Evandro, uma pergunta pessoal minha agora, suponha que você tenha que desenvolver um eCommerce, e na página de detalhes do produto, você mostra aquele slide com imagens do produto, normalmente essas imagens são referenciadas, e você tem (200-300) produtos, e 5 imagens em cada, você guardaria isso tudo em um banco de dados (base64 encoded) e mostraria como data-uri ? ou guardaria a referencia delas no banco ? (MySQL/MongoDB ou Cassandra)

Editado por Andrey Knupp, 18 julho 2012 - 12:21 .
Adicionar informação

  • 0

#16 Evandro Oliveira

Evandro Oliveira

    leia ali -->

  • Membros
  • 4.540 posts

Postado 18 julho 2012 - 19:53

Certo, agora um bench que eu fiz:

Spoiler


Esse resultado para 1000 copias de uma imagem de 128KB (nem todas terão 128KB, talvez você faça resize, talvez guarde a original e o thumb).
Daí depois tenta apertar CTRL+U.

Não vale apena ... sinceramente, você gasta alguns segundos levando em consideração o que o Evandro falou, é mais em conta do que gravar isso no banco (eu acho).
Se quiser fazer o bench sem usar o DB, simples, pega uma imagem de 128KB codifica o base 64, depois faz o looping exibindo o conteúdo..
Spoiler


Informe o resultado e o que você acha.
E ainda leva em consideração o tamanho do trafego de dados entre o servidor php e o banco de dados.
E lembre da concorrência, suponha uns 20 - 30 usuários, claro que você não vai trazer 1000 imagens, pode limitar sua busca a 10 (talvez uma lista), ou coisa assim.

Para testar a concorrência, pode usar o apache benchmark.
Não dá pra fazer todos esses testes agora, mas....

Lembrando também, que isso também vai aumentar o tamanho do arquivo (caso o armazenamento das imagens for no banco), e como você citou um "caching", se você guarda por 5 minutos, e exibe pra 30 usuários, você vai ler um arquivo de no mínimo 3-4 MB a cada requisição.

E provavelmente, qualquer consulta a nodes do documento com jQuery, ou JS Puro, irá demorar (não tenho crtz, não fiz o teste)


Benchmark, por benchmark, fiz o meu, com Postgres.

SQL
Spoiler


Psql.php
Spoiler


Arquivo de testes, para garantir que todas as respostas sejam idênticas
PsqlTest.php
Spoiler

Para executar, tendo o PHPUnit instalado, basta por os dois arquivos no mesmo diretório e rodar um
phpunit PsqlTest.php

O arquivo de profile do XDebug: http://minus.com/mde2sEAxv

Você pode abrir este arquivo pelo NetBeans, acho que pelo Eclipse, pelo PHPStorm, se usar KDE pelo kcachegrind, se usar Windows pelo wincachegrind ou usando um browser com o webgrind

os resultados aqui na minha máquina foram o seguinte:
Spoiler


@Evandro, uma pergunta pessoal minha agora, suponha que você tenha que desenvolver um eCommerce, e na página de detalhes do produto, você mostra aquele slide com imagens do produto, normalmente essas imagens são referenciadas, e você tem (200-300) produtos, e 5 imagens em cada, você guardaria isso tudo em um banco de dados (base64 encoded) e mostraria como data-uri ? ou guardaria a referencia delas no banco ? (MySQL/MongoDB ou Cassandra)


Escrever as imagens como data-uri está fora de cogitação. Nunca sacrificaria as várias formas de caching e compressão nesse cenário.
data-uri pra mim seria uma saída pra um fundo degradê, por exemplo. Não imagens complexas. Às vezes o base64 gerado consegue ser maior que a imagem! Sem contar que eu teria que embutir isso no markup, atrasando a exibição do conteúdo textual.

Se estamos falando de eCommerce, falamos de performance máxima, correto?? Eu optaria por uma lógica sequencial - o produto de ID 6, carregaria as imagens 6-1.jpg, 6-2.jpg, 6-3.jpg, 6-4.jpg e 6-5.jpg. E eu não procurei nada no banco. Eu sei que o ID é 6 pela URL da página. Essas imagens ficariam muito provavelmente numa rede CDN, num outro domínio, livre de cookies, servindo conteúdo compactado por gzip. Entenda, eu não toco em qualquer banco de dados para esse cenário. Porque é desnecessário.

Editado por Evandro Oliveira, 18 julho 2012 - 19:54 .

  • 0

#17 Andrey Knupp Vital

Andrey Knupp Vital

    Web Developer

  • Moderadores
  • 4.434 posts

Postado 18 julho 2012 - 20:10

Entretanto, no final das contas resume-se a não guardar imagens no banco de dados.
Estou errado ? você de qualquer forma tem o objetivo de exibi-la, se for por data-uri, você vai ter aquela string [0...12000] na sua saída, deixando o site todo lento.

Os tipos de campo eu nem discuto não, sei que com BLOB é melhor, é o tipo de campo correto para esse tipo de coisa.
Mas a questão era: É bom ou NÃO guardar imagens no banco de dados.

Sobre o acesso das informações do produto, veja bem, você sabe o ID do produto, mas não sabe quantas fotos são, ali eu e você afirmamos que são 5, mas e se não forem ? de qualquer forma você vai consultar o banco pra pegar as informações, o que eu faço nesse caso de várias imagens, é simplesmente uma coluna TEXT que vai ficar os paths delimitados por ';', na hora eu apenas quebro a string e exibo.

E Evandro, seu teste tá meio errado aí não ? eu não falei sobre tipos de campo, e sim sobre o conteúdo no banco que no final das contas resume-se a exibição dele (de qualquer forma referência ou não, vai cair na tag img).

No post #10, eu digo "os campos BLOB, LONGBLOB, podem ser usados para esse caso".
Logo em seguida, meu teste se baseia na exibição do conteúdo desses campos.

Editado por Andrey Knupp, 19 julho 2012 - 12:04 .

  • 0

#18 mangakah

mangakah

    "L"

  • Membros
  • 1.856 posts

Postado 18 julho 2012 - 21:12

[...] o que eu faço nesse caso de várias imagens, é simplesmente uma coluna TEXT que vai ficar os paths delimitados por ';', na hora eu apenas quebro a string e exibo.
[...]


Desculpe me intrometer, mas não resisti...

Isso pode até ser mais rápido em termos de benchmark (não testei...), mas eu acho muito deselegante e pouco profissional. Eu crio logo um relacionamento (1hasMany) entre a tabela 'produtos' e a tabela 'imagens'. Só de pensar que na hora de adicionar uma imagem onde já haviam umas 20 eu terei que fazer a consulta e depois concatenar a string e por fim enviar de volta ao banco de dados para que o campo seja sobrescrito eu já fico agoniado.
  • 0

#19 Andrey Knupp Vital

Andrey Knupp Vital

    Web Developer

  • Moderadores
  • 4.434 posts

Postado 18 julho 2012 - 21:55

Isso pode até ser mais rápido em termos de benchmark (não testei...), mas eu acho muito deselegante e pouco profissional. Eu crio logo um relacionamento (1hasMany) entre a tabela 'produtos' e a tabela 'imagens'. Só de pensar que na hora de adicionar uma imagem onde já haviam umas 20 eu terei que fazer a consulta e depois concatenar a string e por fim enviar de volta ao banco de dados para que o campo seja sobrescrito eu já fico agoniado.

Certo, da mesma forma que você vai precisar da consulta pra montar o formulário de update, você vai ter essa coluna já com ele.
E da mesma forma que você usa o explode pra poder separar os delimitadores e tem o array de retorno, você faz um push dessa imagem nesse array e um implode com o delimitador novamente.

Pronto, você tem sua nova lista de imagens normalmente.
Eu não tenho problemas com modelagem de banco, afinal nunca usei "de fato" essa solução das imagens que falei, apenas foi o que me veio a cabeça, disse o "faço" para o caso atual em que está sendo discutido, mas ... é questão de analisar a situação.

Com certeza a tabela imagens sendo separada fica muito fácil Atualizar a referencia, remover ... e adicionar, enfim.
Já tive casos em que a situação tem que ser resolvida diretamente no banco, ou seja sem alterar no PHP.

Se quiser, te mostro uma modelagem minha que toda a parte matemática do sistema fica acoplado no SQL, da mesma forma em que existem casos que você cria uma tabela e guarda as imagens e casos que você pensa em outra solução.

Editado por Andrey Knupp, 18 julho 2012 - 21:58 .

  • 0

#20 Evandro Oliveira

Evandro Oliveira

    leia ali -->

  • Membros
  • 4.540 posts

Postado 19 julho 2012 - 14:04

E Evandro, seu teste tá meio errado aí não ? eu não falei sobre tipos de campo, e sim sobre o conteúdo no banco que no final das contas resume-se a exibição dele (de qualquer forma referência ou não, vai cair na tag img).


Procurei não fugir do objetivo inicial do tópico. Guardar a imagem ou o caminho no BD. Se for pra usar a tag IMG não precisaria nem dessa papagaiada toda. Armazena o caminho físico mesmo por todas as desvantagens do base64 já citadas nesse tópico.

Para guardar a imagem, usando Postgres, temos duas formas: Long Object ou encoded.
Para guardar o caminho, eu só conheço uma forma.

Conhecidas todas as possibilidades, criei os testes e isolei as execuções para ter um benchmark mais preciso possível.

Analisando as imagens postadas, vi que havia algo muito errado. Então reiniciei o computador em modo terminal, sem X, sem acesso à Internet e executei os testes 5 vezes
$ php -d xdebug.profiler_enable=1 /usr/local/bin/phpunit --repeat 5 PsqlTest.php

O cachegrind gerado pode ser obtido aqui

Aqui as informações relevantes e a minha dedução sobre a performance:
Imagem postada

Usar o tipo Long Object é o menos performático. Mas se a opção existe, deve ter suas funções, talvez com imagens maiores possa ser mais rápida que codificar em base64.

Fato curioso é que a exclusão da imagem em base64 é sempre mais rápida. Talvez o Postgres apenas remova a referência ao campo TEXT ao invés de truncá-lo, como faz com varchar.

Para inserção e consulta, armazenar apenas o caminho físico e abrí-lo externamente se mostrou o menos latente. Por motivos óbvios.

Ao contrário da sequência que eu imaginava, armazenar um conteúdo binário no Postgres envolve um passo a mais ao invés de um passo a menos - lo_export e lo_import. Como eu disse, deve ter sua utilidade.

Como esperado, base64 não parece ser uma solução muito inteligente por criar a mesma camada de necessidade do tipo Long Object (lo_export -> base64_decode, lo_import -> base64_encode).

Excetuando-se pela exclusão, usar apenas o caminho físico do arquivo é mais rápido em todos os cenários. Usei a função copy para simular a funcionalidade de move_uploaded_file e ter um resultado mais próximo possível do real.


Sobre o acesso das informações do produto, veja bem, você sabe o ID do produto, mas não sabe quantas fotos são, ali eu e você afirmamos que são 5, mas e se não forem ? de qualquer forma você vai consultar o banco pra pegar as informações, o que eu faço nesse caso de várias imagens, é simplesmente uma coluna TEXT que vai ficar os paths delimitados por ';', na hora eu apenas quebro a string e exibo.


http://php.net/glob
  • 0




Publicidade

/ins>