Afbeeldingen opslaan in database

Pagina: 1
Acties:

Onderwerpen


  • ZeroXT
  • Registratie: December 2007
  • Laatst online: 14:37
Beste tweakers,

Ik heb een site met wallpapers waarbij de afbeeldingen fysiek op de harde schijf staan. Deze wallpapers hebben een resolutie tussen de 800x600 en 3840x2400 en zijn tussen de 100KB en 4MB groot.

De gebruiker heeft de mogelijkheid om elk wallpaper in elk gewenste resolutie te downloaden omdat het systeem deze (met een extern programma) on the fly resized met het behouden van de verhouding. Vervolgens zal deze nieuwe resolutie voor de desbetreffende wallpaper fysiek opgeslagen worden zodat deze later niet opnieuw on the fly aangepast hoeft te worden.

Tijdens het ophalen/downloaden van de wallpaper wordt deze via PHP aangeboden zodat er in de database een teller bijgehouden kan worden om het aantal downloads weer te geven. Dat doe ik met de functie fopen() van PHP:


PHP:
1
2
3
4
5
6
7
8
9
if($fd = fopen('wallpaper.jpg', 'r'))
{
    while(!feof($fd))
    {
        echo fread($fd, 2048);
    }
                
    fclose($fd);
}


Nu kwam ik laatst op een artikel uit en dat bracht mij op een idee. Als ik alle wallpapers tijdens het uploaden base 64 encode in die string in de database opsla, heb ik meer controle en minder code nodig om fysieke wallpapers te verplaatsten of te verwijderen. Omdat ik de wallpapers toch al eerst ophaal met PHP leek het me geen gek idee om deze dan in de database te zetten.

Alleen nu vraag ik me af of dit wel efficiënt is en of het überhaupt een slim idee is. Wellicht dat ik alsnog dingen over het hoofd zie (bijvoorbeeld geheugengebruik) en wellicht is het een nadeel dat de database hierdoor enorm groot wordt.

Heeft iemand hier ervaringen mee of opmerkingen? :)

Mocht het een goed idee zijn, is het ook een goed idee om dit voor de thumbnails te doen? Deze worden echter niet eerst opgehaald door PHP en zijn dus direct benaderdbaar dus wellicht dat het in dit geval minder efficiënt is vanwege de snelheid en geheugen gebruik?

  • storeman
  • Registratie: April 2004
  • Laatst online: 11:48
Vraag jezelf dit eens af:

1. Hoeveel downloads verwacht je per maand
2. Wat is het voordeel van het opslaan in de database?

Voor elke thumbnail ga je een query uitvoeren, lijkt me niet erg efficient. Maar als je 10000 views per maand hebt, zal dat geen probleem zijn. Dit soort issues komen later pas de kop opsteken. Zelf zou ik een consequente bestandsstructuur opzetten. Nu is db naar filesystem altijd een minder zekere koppeling dan dat je alles in de database zet, dus je insteek snap ik. Alleen is die data integriteit niet dermate belangrijk dat dit kan verantwoorden om de data in de database te zetten.

Als laatste wil ik nog opmerken dat base_64 hier totale overkill is, bijna elke database ondersteunt het opslaan van binaire data. Dat is het, en dat blijft het. De RDBMS gaat met binaire data anders om dan met text, dit heeft vele performance voordelen. Dus als je het in de DB wilt stoppen, verdiep je daar even in :).

"Chaos kan niet uit de hand lopen"


  • huiser
  • Registratie: Mei 2003
  • Laatst online: 13-08 10:47
Ik zou het niet doen. Je database kan beter referenties (file paths) naar verschillende varianten van je plaatjes opslaan, i.p.v. de (base64-encoded) binaire data. Die plaatjes bezetten ook je (kostbare) database cache.
Tevens wordt je backup veeel groter, en zal deze ook langer gaan duren. Dit kan een langere performance-impact hebben op je database.

-Huiser


  • storeman
  • Registratie: April 2004
  • Laatst online: 11:48
huiser schreef op donderdag 06 september 2012 @ 09:58:
Ik zou het niet doen. Je database kan beter referenties (file paths) naar verschillende varianten van je plaatjes opslaan, i.p.v. de (base64-encoded) binaire data. Die plaatjes bezetten ook je (kostbare) database cache.
Tevens wordt je backup veeel groter, en zal deze ook langer gaan duren. Dit kan een langere performance-impact hebben op je database.
Binaire data wordt meestal niet gecached door een RDBMS, dus dat is niet echt een argument. Bestanden in een database zetten is al tijden niet zo'n probleem meer.

Het back-up argument vind ik niet echt valide, je moet de bestanden ook back-uppen. Qua backup is alles in de DB zelf nog makkelijker.

"Chaos kan niet uit de hand lopen"


  • ZeroXT
  • Registratie: December 2007
  • Laatst online: 14:37
Bedankt voor de antwoorden, ik ben er alleen nog niet helemaal achter. Ik heb ondertussen op deze pagina gekeken en kwam uit op het volgende:

Nadelen:
- select * from zal een groter resultaat opleveren.
- Geheugengebruik
- Grotere DB load en meer connecties

Voordelen:
- Het gebruik van de beveiliging van de database voor je bestanden
- Er hoeft maar een "bestand" gebackupt te worden

Nadeel nummer 1 heb ik echter niet. Ik gebruikt nooit het sterretje (*) in mijn queries (zelfs niet als ik alles moet selecteren). Nadeel 2 heb ik geloof ik nu ook alleen dan met PHP. Aangezien PHP de bestanden ophaalt zal deze ook in het geheugen gezet moeten worden (?).

Iemand suggesties om het touw door te knippen? :)

  • huiser
  • Registratie: Mei 2003
  • Laatst online: 13-08 10:47
storeman schreef op donderdag 06 september 2012 @ 10:00:
[...]


Binaire data wordt meestal niet gecached door een RDBMS, dus dat is niet echt een argument. Bestanden in een database zetten is al tijden niet zo'n probleem meer.

Het back-up argument vind ik niet echt valide, je moet de bestanden ook back-uppen. Qua backup is alles in de DB zelf nog makkelijker.
Hij gaat de binaire data met Base64 encoding als string opslaan in de database, dus dat wordt wel degelijk gecached.

Als je met rsync of iets dergelijks backups maakt van je plaatjes, dan worden alleen nieuwe en gewijzigde plaatjes gebackupd, i.p.v. alles opnieuw in een grote SQL-dump. Je backups duren dan onnodig veel langer en kosten veel meer ruimte.
Tevens is het voor performance ook veel beter als je plaatjes direct door je webserver laat serveren, i.p.v. het elke keer door je applicatie uit de database te moeten trekken, en via Base64-decoding weer te converteren naar JPG, PNG of whatever.

-Huiser


  • ZeroXT
  • Registratie: December 2007
  • Laatst online: 14:37
huiser schreef op donderdag 06 september 2012 @ 10:56:
[...]Hij gaat de binaire data met Base64 encoding als string opslaan in de database, dus dat wordt wel degelijk gecached.
Inmiddels ben ik van mening dat als ik de afbeeldingen opsla in de database, ik deze niet in Base64 ga encoden om caching te voorkomen.
huiser schreef op donderdag 06 september 2012 @ 10:56:
[...]Tevens is het voor performance ook veel beter als je plaatjes direct door je webserver laat serveren, i.p.v. het elke keer door je applicatie uit de database te moeten trekken, en via Base64-decoding weer te converteren naar JPG, PNG of whatever.
De afbeeldingen worden sowieso niet direct door apache geserveerd maar door PHP vanwege beveiliging en controle.

[ Voor 7% gewijzigd door ZeroXT op 06-09-2012 11:03 ]


  • messi
  • Registratie: Oktober 2001
  • Laatst online: 09:41
ZeroXT schreef op donderdag 06 september 2012 @ 11:02:

De afbeeldingen worden sowieso niet direct door apache geserveerd maar door PHP vanwege beveiliging en controle.
Waarom stream je de bestanden door php heen, dat is niet echt efficient.

Gebruik bijvoorbeeld X-Sendfile / X-Accel-Redirect en laat je webserver doen waar ie goed in is :)

Onze excuses voor het ontbreken van de ondertiteling.


  • ZeroXT
  • Registratie: December 2007
  • Laatst online: 14:37
messi schreef op donderdag 06 september 2012 @ 11:08:
[...]Waarom stream je de bestanden door php heen, dat is niet echt efficient.

Gebruik bijvoorbeeld X-Sendfile / X-Accel-Redirect en laat je webserver doen waar ie goed in is :)
X-Accel-Redirect is voor nginx terwijl ik Apache draai. X-Sendfile heb ik al enig tijd geleden geprobeerd maar het had niet het gewenste resultaat. Het gaat in dit topic niet of de webserver of PHP efficiënter is voor versturen van afbeeldingen maar of het efficiënt is om de afbeeldingen te verplaatsen naar de database.

Toch wil ik je bedanken voor het meedenken. Mocht het alsnog geen goed idee zijn om de afbeeldingen op te slaan in de database, dan zal ik zeker weer kijken naar de module X-Sendfile, so thank you for the reminder. :)

Anyone? :)

  • azerty
  • Registratie: Maart 2009
  • Laatst online: 20:56
Wat je misschien ook nog kunt doen is de thumbs in het echt opslaan, die wijzigen toch niet, en de verschillende groottes wel in je db? Kan een hoop queries schelen, en lijkt me relatief gezien beter. Veel mensen gaan de thumbs inladen om door pagina's te bladeren, ziet het er interssant uit klikken ze voor detail...

  • Hydra
  • Registratie: September 2000
  • Laatst online: 21-08 17:09
ZeroXT schreef op donderdag 06 september 2012 @ 11:15:
X-Accel-Redirect is voor nginx terwijl ik Apache draai. X-Sendfile heb ik al enig tijd geleden geprobeerd maar het had niet het gewenste resultaat. Het gaat in dit topic niet of de webserver of PHP efficiënter is voor versturen van afbeeldingen maar of het efficiënt is om de afbeeldingen te verplaatsen naar de database.
Voor een kleine site maakt het sowieso geen fluit uit en kun je het beste gaan voor de meest practische oplossing. Als dat voor jou het opslaan van binaire blobs in je DB is, moet je dat gewoon doen. Zorg in ieder geval wel dat als je plaatjes serveert dat deze door de client gecached kunnen worden.
wsitedesign schreef op donderdag 06 september 2012 @ 11:52:
Wat je misschien ook nog kunt doen is de thumbs in het echt opslaan, die wijzigen toch niet, en de verschillende groottes wel in je db? Kan een hoop queries schelen, en lijkt me relatief gezien beter. Veel mensen gaan de thumbs inladen om door pagina's te bladeren, ziet het er interssant uit klikken ze voor detail...
Doodsimpele selects op een index zijn sowieso geen enkel issue voor MySQL. Daarnaast zorg je dat plaatjes door de client gecached kunnen worden en dan hoef je de data niet opnieuw te sturen.

[ Voor 30% gewijzigd door Hydra op 06-09-2012 12:52 ]

https://niels.nu


  • ZeroXT
  • Registratie: December 2007
  • Laatst online: 14:37
Hydra schreef op donderdag 06 september 2012 @ 12:51:
[...]Voor een kleine site maakt het sowieso geen fluit uit en kun je het beste gaan voor de meest practische oplossing. Als dat voor jou het opslaan van binaire blobs in je DB is, moet je dat gewoon doen. Zorg in ieder geval wel dat als je plaatjes serveert dat deze door de client gecached kunnen worden.
Het wordt een site met ongeveer 15.000 unieke wallpapers (dus originele resoluties die nog naar gecropte resoluties kan worden geresized)

  • F_J_K
  • Registratie: Juni 2001
  • Niet online

F_J_K

Moderator CSA/PB

Front verplichte underscores

Zeg gemiddeld 2MB groot origineel, dan dus 30GB aan originelen en tzt evenveel aan kleinere versies is 60GB aan binaire data. Op zich geen enorme hoeveelheden, maar vanuit alleen al backupsnelheid-perspectief zou ik dan toch sneller kiezen voor losse bestanden. Dat lijkt mij (als niet-devver) dat ook eenvoudiger te scheiden naar verschillende servers (fileserver vs DBserver) mocht dat qua performance ooit handig blijken.

'Multiple exclamation marks,' he went on, shaking his head, 'are a sure sign of a diseased mind' (Terry Pratchett, Eric)


  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 10:54

Janoz

Moderator Devschuur®

!litemod

Persoonlijk zou ik het onderscheid maken tussen 'bron' data en afgeleide data. Afgeleide data is, zoals het al uit de term blijkt, data welke afgeleid is. Dat dit verloren gaat is niet een groot probleem aangezien het gewoon weer afgeleid zou kunnen worden. Bron data is dat niet.

Dit toepassende op je huidige situatie zou ik denken:

- Sla het origineel op in de database (in een BLOB)
- Sla alle geresizede afbeeldingen op in een cache map

Het kwijtraken van die cache map is geen enkel probleem (los van performance) aangezien die gewoon weer opnieuw gegenereerd kunnen worden uit het origineel welke in de database zit.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


  • Cyphax
  • Registratie: November 2000
  • Laatst online: 23:06

Cyphax

Moderator LNX
F_J_K schreef op donderdag 06 september 2012 @ 14:06:
Zeg gemiddeld 2MB groot origineel, dan dus 30GB aan originelen en tzt evenveel aan kleinere versies is 60GB aan binaire data. Op zich geen enorme hoeveelheden, maar vanuit alleen al backupsnelheid-perspectief zou ik dan toch sneller kiezen voor losse bestanden. Dat lijkt mij (als niet-devver) dat ook eenvoudiger te scheiden naar verschillende servers (fileserver vs DBserver) mocht dat qua performance ooit handig blijken.
Het is een beetje afhankelijk van je database, maar je kunt er dan voor kiezen om de blobs in een andere filegroup op te slaan. Daar kun je dan rekening mee houden bij het backuppen. :)
SQL Server kan het iig wel.
http://stackoverflow.com/...ring-images-in-sql-server heeft ook wel interessante informatie voor je denk ik.

Saved by the buoyancy of citrus


Acties:
  • 0 Henk 'm!

  • Boss
  • Registratie: September 1999
  • Laatst online: 10:56

Boss

+1 Overgewaardeerd

Ik heb een paar jaar geleden een oplossing gemaakt waarbij ook binary bestanden in een database worden opgeslagen. Dat werkt nu een paar jaar naar volle tevredenheid met inmiddels ruim 100k documenten.

Het enige probleem is inderdaad de backup. Nu gaat deze on-site en dan is het wel te doen. Maar voor een off-site backup is het niet te doen om het hele bestand te uploaden tijdens iedere backup. Daar zit je met losse files toch een stuk beter, het is niet moeilijk om uit te zoeken welke bestanden gewijzigd zijn.

The process of preparing programs for a digital computer is especially attractive, not only because it can be economically and scientifically rewarding, but also because it is an aesthetic experience much like composing poetry or music.


Acties:
  • 0 Henk 'm!

  • Compuhair
  • Registratie: September 2009
  • Nu online
Waarom sla je de afbeeldingen niet op in Windows Azure Blob storage, of een andere bestandenopslag in de cloud?

Het voordeel hiervan is dat je plaatjes direct benaderbaar zijn voor anderen, eventueel beveiligd. Dus ze worden niet via jouw database/fileserver/webserver gestreamd, maar kunnen gedownload worden vanuit de cloud door de eindgebruiker. Je hoeft je niet druk te maken over backups omdat alles automatisch voor jou gerepliceerd wordt. Bovendien is het goedkoop en schaalbaar. Alhoewel met 30GB aan data dat waarschijnlijk geen issues zullen zijn.

Overigens zijn er ook api's voor andere talen dan PHP, zoals .NET, Java, node.js en Python.

Acties:
  • 0 Henk 'm!

  • BasieP
  • Registratie: Oktober 2000
  • Laatst online: 22-07-2024
Compuhair schreef op vrijdag 07 september 2012 @ 12:58:
Waarom sla je de afbeeldingen niet op in Windows Azure Blob storage, of een andere bestandenopslag in de cloud?

Het voordeel hiervan is dat je plaatjes direct benaderbaar zijn voor anderen, eventueel beveiligd. Dus ze worden niet via jouw database/fileserver/webserver gestreamd, maar kunnen gedownload worden vanuit de cloud door de eindgebruiker. Je hoeft je niet druk te maken over backups omdat alles automatisch voor jou gerepliceerd wordt. Bovendien is het goedkoop en schaalbaar. Alhoewel met 30GB aan data dat waarschijnlijk geen issues zullen zijn.

Overigens zijn er ook api's voor andere talen dan PHP, zoals .NET, Java, node.js en Python.
owja zoek dan ook een cloud die genoeg uptime en backups garandeert. Tevens moet je kijken naar wat zij mogen doen met jou data.
Je creeert een afhankelijkheid en de vraag is natuurlijk of je dit wilt.


Nog iets (hydra gaf het ook al aan)
zorg vooral dat je de juiste headers gaat meesturen. Zorg dat je browser de juiste keuzes kan maken. Sla dus bij een afbeelding in de database ook de laatste wijzigingsdatum op, en stuur deze mee als header.

Je browser kan dan beslissen of hij uberhaupt de afbeelding (of thumb for that matter) wel wil ophalen.
Zoek eens naar 304 response header.

This message was sent on 100% recyclable electrons.


Acties:
  • 0 Henk 'm!

  • Compuhair
  • Registratie: September 2009
  • Nu online
BasieP schreef op dinsdag 11 september 2012 @ 19:40:
[...]

owja zoek dan ook een cloud die genoeg uptime en backups garandeert. Tevens moet je kijken naar wat zij mogen doen met jou data.
Je creeert een afhankelijkheid en de vraag is natuurlijk of je dit wilt.
Als je zelf een servertje onder je bureau verstopt, dan zit je natuurlijk ook met het probleem van uptime en backups. Bovendien moet je dan ook nog zelf voor OS-updates, security patches etc. zorgen.

Je creeërt inderdaad een extra afhankelijkheid als je een externe hoster of cloud provider kiest, maar krijgt daar bij de juiste keuze veel gemak en zekerheid voor terug.

Acties:
  • 0 Henk 'm!

  • BasieP
  • Registratie: Oktober 2000
  • Laatst online: 22-07-2024
Compuhair schreef op dinsdag 11 september 2012 @ 20:12:
[...]


Als je zelf een servertje onder je bureau verstopt, dan zit je natuurlijk ook met het probleem van uptime en backups. Bovendien moet je dan ook nog zelf voor OS-updates, security patches etc. zorgen.

Je creeërt inderdaad een extra afhankelijkheid als je een externe hoster of cloud provider kiest, maar krijgt daar bij de juiste keuze veel gemak en zekerheid voor terug.
Ik neem aan dat hij een hoster heeft. Ik had het niet over een eigen server.
Tevens raad ik niets af of aan, maar zeg alleen even wat hij in overweging moet nemen.

Wanneer je je hosting splitst (dus zowel normale webhost+db, en een cloud oplossing voor je images) heb je gewoon meer afhankelijkheden. Je site werkt nu niet meer wanneer 1 van beide gek doet.

Iets wat ik verder nog niet eens als argument gezegd had is dat je misschien wel authenticatie wilt voor toegang tot images. Wanneer je zelf voor een (bijv. php) oplossing kiest (zoals de TS nu doet) is dit makkelijker in je site in te bouwen dan wanneer je jouw eigen auth systeem moet koppelen met die van die cloudoplossing.

This message was sent on 100% recyclable electrons.

Pagina: 1