[PHP5/MySQL] Afbeeldingen opslaan in database

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • Noxious
  • Registratie: Juli 2002
  • Laatst online: 19-09 22:46
Ik heb eens het internet overgebrowsed om uit te vinden hoe je het beste afbeeldingen kan opslaan in een database, in dit geval MySQL.
Als ik het zo lees gaat dit (logisch) het beste in een BLOB-veld, maar ik lees ook heel veel adviezen om alleen het path op te slaan en de image dan te uploaden in een mapje waar je dmv htaccess niet direct toegang tot hebt en dat laten inlezen door een phpscript (plaatjes moeten bij opvragen worden gemotificeerd) op basis van ID (uit een database) die weer linkt naar de file.

Wat is jullie advies hierin?
Wat is wijsheid?

Ik heb nu twee opties:
- Opslaan in de database, het enige nadeel wat ik weet is dat de database _groot_ wordt, zijn er meer nadelen?
- Opslaan op schijf, php roept MySQL aan, die returned het path, inlezen in php, aanpassen en outputten met image headers.

Acties:
  • 0 Henk 'm!

  • Maghiel
  • Registratie: Maart 2004
  • Laatst online: 17:22
[google]storing images on file system versus storing images in database[/google]

[ Voor 39% gewijzigd door Woy op 07-05-2009 09:08 ]


Acties:
  • 0 Henk 'm!

  • vdvleon
  • Registratie: Januari 2008
  • Laatst online: 08-06-2023
Ik zou dat advies opvolgen.
Je kan de afbeelding in een berschermde map opslaan, maar dit heeft wel nadelen dat als je 2 bestanden met de zelfde naam hebt, dat 1 van de twee bestanden de ander overschrijft.

Dus je kunt het beste het volgende doen:
- Iemand upload een afbeelding (dat is het geval neem ik aan)
- Je verzint een nieuwe bestandsnaam (willekeurig)
- Je slaat de afbeelding op in een map (kan gebeveiligd of alleen de list functie uitschakkelen ( .htaccess Options -Indexes))
- In je database sla je het originele bestandsnaam op en de willekeurige nieuwe bestandsnaam

Als je nu een afbeelding wilt benaderen haal je deze uit de database en kan je de link sturen naar de gebruiker. Mocht de originele bestands naam niet relevant zjin, dan sla je deze natuurlijk niet op ;)

Acties:
  • 0 Henk 'm!

  • Noxious
  • Registratie: Juli 2002
  • Laatst online: 19-09 22:46
@vdvleon: Mja de afbeeldingsnaam zou sowieso gewoon de ID uit de database worden dan + willekeurige md5 hash zodat een andere afbeelding niet zo makkelijk te raden is als de map niet beveiligd zou zijn, dus altijd uniek ;)
Veel bestanden zullen echter door php heen moeten voor aanpassingen op het moment van opvragen, dan lijkt het uit de database halen van een afbeelding me sneller incl 'live' resizen (zodat ie maar 1x opgeslagen hoeft te worden, bij direct linken in het geval van niet aanpassen mbv php (dat is niet altijd zo) moet ie in meerdere grotes opgeslagen worden) en 'bewerken' van het bestand in php. In het geheugen geladen wordt 'ie toch al op de server omdat dat nou eenmaal nodig is en dan lijkt lezen van een file me trager dan uit MySQL.
De 'php doet image lezen en outputten' overhead is er toch al bijna altijd.

@Maghiel: Tnx :) ik vond veel waardelozere results. Ik heb o.a. http://www.webmasterworld.com/forum88/9091.htm gelezen en als ik die als voorbeeld neem en die punten aanpak:

- Performance: zie mijn lap tekst hierboven, daar zit ik alsnog mee als in het niet in MySQL stop aangezien het dan ook door php heen moet. Voor mij dus geen issue. MySQL kan hier zelfs voordeel hebben denk ik, maar dat zou ik moeten testen.
- Storage: Hetzelfde, behalve dat recovery inderdaad wat moeilijker kan gaan zijn met een hele grote table, dat is nog m'n enige 'probleem'. Uiteraard kan ik de uiteindelijke image data in een aparte tabel in een aparte database stoppen zodat dat probleem al een stuk kleiner is en vergelijkbaar met het filesystem-probleem.
- Portability: Ook niet echt een issue, daar zou MySQL zelfs makkelijker (kunnen) zijn aangezien de beveiliging op mapniveau niet van toepassing is (opendir tegengaan). Dan is het ook een stuk makkelijker te moven tussen Windows en Linux servers indien nodig. Standaard zal het op een Linux server gaan draaien overigens.

Bedankt voor jullie input alvast :) zie ik nog iets wereldschokkends over het hoofd?

Acties:
  • 0 Henk 'm!

  • vdvleon
  • Registratie: Januari 2008
  • Laatst online: 08-06-2023
Ik heb al meerdere gallery scripts geschreven. Ik weet niet waar het hier om gaat. Maar ik deed dat altijd als volgd:

Ik upload een image (jpg). Deze resize ik met mijn script naar 2 grotes, de thumb en de big. De thumb moet bijv. altijd binnen 100x100 blijven, en de big binnen de 800x600. Voor bijde gegenereerde afbeeldingen verzon ik een willekeurige naam en sloeg deze bijde op in de database. Als je dan bijv. een album X wilt weergeven, haal je gewoon alle afbeeldingen uit de database en geef je de thumbs weer. Klik je op een thumb, dan geeft de big weer. Een simpel princiepe, en overhead? Waarom, php behandeld die upgeloade afbeelding maar 1 keer en vervolgend hoeft de client via http alleen nog maar die afbeelding te downloaden.

Maar misschien is het handig als je uitlegd wat je er precies mee doet...

Acties:
  • 0 Henk 'm!

  • Kwastie
  • Registratie: April 2005
  • Laatst online: 19-09 10:42

Kwastie

Awesomeness

Het opslaan van binaire data in een database is niet aan te raden. Dus optie 1 valt dan af.

Het beste kun je deze data opslaan op de harddisk en in de database een verwijzingen maken het bestand.

Let wel op dat je bestandsnaam niet dubbel mak voorkomen in je database en harde schijf. Je kan hem dan bijvoorbeeld opslaan als: Originele_filename + tijd.

When I get sad i stop being sad and be awesome instead


Acties:
  • 0 Henk 'm!

  • vdvleon
  • Registratie: Januari 2008
  • Laatst online: 08-06-2023
@Kwastie

Lees mijn berichten eens. Lijken wel beetje op elkaar. Maar idd, dat lijkt mij het makkelijkst, logischt, en het beste voor de server ;)

Acties:
  • 0 Henk 'm!

  • TeeDee
  • Registratie: Februari 2001
  • Laatst online: 20:02

TeeDee

CQB 241

Dus als ik je goed begrijp wil je een afbeelding van formaat x opslaan in een BLOB. De afbeelding moet gemodificeerd worden naar bijvoorbeeld formaat y. Hoe kom je erop dat het sneller zal zijn als dit in een DB opgeslagen wordt? In principe wordt dit inderdaad altijd afgeraden, maar goed, the right tool for the job zullen we maar zeggen.

Als je enkel de filename opslaat is dit makkelijker te indexeren, sneller op te zoeken, de overhead op de tables wordt vele malen kleiner en het filesystem is in principe sneller dan je DB.

Als je bijvoorbeeld je table in het geheugen van je DB kan plaatsen kan je daar weer snelheidswinst vandaan halen natuurlijk.

Het aanpassen in PHP en returnen e.d. zal je ook moeten doen als je het via een BLOB veld gaat doen.

Best practice is nu eenmaal: hou een file daar waar het hoort: je filesystem. Backup zaken lijken mij in principe ook makkelijker te doen als je het op je FS houdt dan in 1 heeuull groot DB bestand. Tenzij je een soort van sharding systeem gaat gebruiken.

En last but not least (om de verwarring compleet te maken ;)): meten is weten.

Heart..pumps blood.Has nothing to do with emotion! Bored


Acties:
  • 0 Henk 'm!

  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
Tsja, voor alletwee valt wat te zeggen.

Voor dbase :
- Je backup proces wordt veel simpeler ( enkel 1 dbase ipv vele losse plaatjes )
- je web backend wordt simpeler ( alles praat alleen maar tegen 1 dbase, niet 1 dbase en 1 filebase en en en... )

Tegen dbase :
- Je veroorzaakt veel meer data van en naar je dbaseserver ( wordt relevant als je je dbase server apart gaat zetten ipv localhost )
- Je lokale beheer wordt moeilijker ( ipv 1 laptop aansluiten en even met windows verkenner alle plaatjes langsscannen moet je nu 1 complete beheertool bouwen )

In theorie is opslaan op het lokale filesysteem sneller, maar als je grappen als resizen ( voor bijv thumbnails ) etc gaat uithalen zou ik al kiezen voor een lokale filesystem cache.
Met een goede en efficiente cache schakel je imho alle problemen uit en ( mits je in dbase opslaat ) kan je ook nog eens supermakkelijk een webserver erbij knallen, je cache vult zichzelf wel weer aan.

Als je het in een dbase opslaat zijn er wel een aantal dingen waar op te letten ( blob's in een gewoon gebruikte tabel zijn in bijv mysql niet handig, probeer altijd een aparte tabel hiervoor te gebruiken ) maar met een efficiente cache hoeft het qua snelheid etc niets uit te maken, waardoor het puur op het beheersstuk aankomt...

Acties:
  • 0 Henk 'm!

  • Cartman!
  • Registratie: April 2000
  • Niet online
Ik zou ze dan buiten webroot plaatsen en met fpasstrough serveren. Eventueel thumbs maken als je die nodig hebt tijdens het uploaden of eenmalig tijdens de eerste serving en dan cachen. Ik heb t nooit op images opslaan in de DB.

Acties:
  • 0 Henk 'm!

  • YopY
  • Registratie: September 2003
  • Laatst online: 13-07 01:14
Ik zal een aantal centen toevoegen.

* Afbeeldingen in een database zijn slecht indexeerbaar door zoekmachines
* Afbeeldingen in een database zijn verre van efficient, je moet een PHP script + databasequery uitvoeren voor elke afbeelding of groep afbeelding, de hele afbeelding in het geheugen van je server proppen, etc. Afbeelding op de server zelf is veel vlotter en efficiënter
* Geef je bestandsnamen wel logische namen, dwz rename ze niet naar een timestamp of MD5 hash maar geef ze een naam die voor een deel beschrijft wat er in staat. Ook weer voor zoekmachines, maar ook voor je gebruikers als ze een afbeelding op willen slaan.
* Voordat je een bestand opslaat controleer je of een bestand met dezelfde naam al bestaat, dmv een eenvoudig loopje zoals dit:

code:
1
2
3
4
5
6
7
$filename = bestandsnaam;
$tmpfilename = $filename
$i = 1;
while (exists($tmpfilename)) {
    $tmpfilename = $filename + $i;
}
save($tmpfilename);


(eenvoudig voorbeeld overigens)

Zo voorkom je dat je dubbele bestanden opslaat zonder dat je het jezelf al te moeilijk maakt met MD5 of timestamps (die mogelijk dubbele waarden kunnen hebben.

Acties:
  • 0 Henk 'm!

  • Noxious
  • Registratie: Juli 2002
  • Laatst online: 19-09 22:46
Het resizen is niet het probleem ;) ik neig ook al naar de filesystem optie ivm backup en recovery enzo maar:
- php gaat er ook data overheen zetten die 'live' moet zijn op het moment van opvragen, zoals de huidige tijd bijv.

Oftewel, het is nooit een normale http transfer van de file bij het opvragen, hij moet sowieso altijd door php heen.

Voor de snelheidsmeting zal ik wel een testcase moeten schrijven ;) soon eens doen dus, als filesystem dan sneller is dan wordt dat de definitieve optie :)

Acties:
  • 0 Henk 'm!

  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
[quote]YopY schreef op donderdag 07 mei 2009 @ 09:28:
Ik zal een aantal centen toevoegen.
* Afbeeldingen in een database zijn slecht indexeerbaar door zoekmachines
Waarom? Zolang je geen opendirs hebt staan zie ik niet echt wat het uitmaakt voor een zoekmachine...
* Afbeeldingen in een database zijn verre van efficient, je moet een PHP script + databasequery uitvoeren voor elke afbeelding of groep afbeelding, de hele afbeelding in het geheugen van je server proppen, etc. Afbeelding op de server zelf is veel vlotter en efficiënter
Tsja, als je er toch al php bewerkingen overheen moet gooien dan praat je alleen nog maar over het verschil tussen db call en fs call. Zal ook niet echt een wereld van verschil zijn ( wel bij kleine bestandjes, maar als je er 2 miljoen hebt maakt dit niets meer uit )
* Geef je bestandsnamen wel logische namen, dwz rename ze niet naar een timestamp of MD5 hash maar geef ze een naam die voor een deel beschrijft wat er in staat. Ook weer voor zoekmachines, maar ook voor je gebruikers als ze een afbeelding op willen slaan.
Wederom waarom? Zolang je geen opendir hebt is dit allemaal triviaal om op te lossen in scripting...
Andersom is een iets grotere uitdaging, geen dubbele afbeeldingen opslaan etc.
Zo voorkom je dat je dubbele bestanden opslaat zonder dat je het jezelf al te moeilijk maakt met MD5 of timestamps (die mogelijk dubbele waarden kunnen hebben.
Serieus, je maakt je druk over de mogelijke dubbele waardes van md5 dus zet je maar iets achter de bestandsnaam? Tegen de tijd dat je de 1e md5 clash hebt zit je al tig jaar over de max lengte van bestandsnamen heen...

Acties:
  • 0 Henk 'm!

Verwijderd

Voor onze situatie , 50.000 artikelen met elk minimaal 2 afbeeldingen, hebben we een systeem gemaakt welke de orrginele afbeeldingen wegschrijft op de HD en in de DB de link naar de file zet.
Doormiddel van een script kunnen we nu elk gewenst formaat met elk gewenste afmeting uit het systeem halen. Werkt prima..
Goede caching er achter en je hebt een top systeem!

Wij hebben de testcase eerst ook gedaan en kwam er gewoon uit dat filesysteem manier de snelste was. Maar we praten dan wel over een systeem welke ruim 100.000 artikel afbeeldingen huisvest welke allemaal in hi-res geschoten zijn!
Nadeel was wel dat dit alles op een aparte machine moest draaien! maar ja wat kost tegen woordig een extra machine!

owjah alle muaties gaan dmv een paar pagina's die alles in de DB veranderen! dubbele filesnames hebben we eigenlijk niet door het slim linken van afbeeldingen aan artikelen..

[ Voor 11% gewijzigd door Verwijderd op 07-05-2009 09:50 ]


Acties:
  • 0 Henk 'm!

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

Janoz

Moderator Devschuur®

!litemod

Kwastie schreef op woensdag 06 mei 2009 @ 21:41:
Het opslaan van binaire data in een database is niet aan te raden. Dus optie 1 valt dan af.
Onzin. Waar denk je dat 'data' in database voor staat?
YopY schreef op donderdag 07 mei 2009 @ 09:28:
* Afbeeldingen in een database zijn slecht indexeerbaar door zoekmachines
Onzin. Dat is puur afhankelijk van de implementatie en is absoluut niet gekoppeld aan het opslaan in de database. Een leuke url rewrite lost dit probleem zo op. Voor de buitenkant is er geen enkel verschil tussen een scriptje dat adhv een id een plaatje van de schijf haalt en 'fpassthrough'-t of uit de database haalt.
* Afbeeldingen in een database zijn verre van efficient, je moet een PHP script + databasequery uitvoeren voor elke afbeelding of groep afbeelding, de hele afbeelding in het geheugen van je server proppen, etc. Afbeelding op de server zelf is veel vlotter en efficiënter
Vast minder efficient dan filesystem, maar zodra je ook maar iets extra's wilt doen (authorizaties ed) zul je sowieso al een database verbinding per afbeelding op gaan zetten om de meta data binnen te halen. Dat maakt het verschil alvast een stuk kleiner.

Daar tegenover staan vervolgens wel weer een bak voordelen. Reverentiele integriteit die door de DB afgedwongen wordt. Backups die een stuk makkelijker gaan en niet out of sync zijn. In het kort komt het er op neer dat je applicatie misschien wat minder efficient is, maar daarintegen een stuk makkelijker te beheren en onderhouden is.
* Geef je bestandsnamen wel logische namen, dwz rename ze niet naar een timestamp of MD5 hash maar geef ze een naam die voor een deel beschrijft wat er in staat. Ook weer voor zoekmachines, maar ook voor je gebruikers als ze een afbeelding op willen slaan.
Leuk idee, maar in de praktijk levert dit alleen nog maar meer problemen op. Daarnaast lijken me timestamp en MD5 ook niet echt beste keuzes. Neem gewoon het ID van het record met de metadata. Gegarandeerd uniek.
* Voordat je een bestand opslaat controleer je of een bestand met dezelfde naam al bestaat, dmv een eenvoudig loopje zoals dit:

code:
1
2
3
4
5
6
7
$filename = bestandsnaam;
$tmpfilename = $filename
$i = 1;
while (exists($tmpfilename)) {
    $tmpfilename = $filename + $i;
}
save($tmpfilename);


(eenvoudig voorbeeld overigens)

Zo voorkom je dat je dubbele bestanden opslaat zonder dat je het jezelf al te moeilijk maakt met MD5 of timestamps (die mogelijk dubbele waarden kunnen hebben.
Race probleem...





Er is niet een juiste en een verkeerde keuze. Beide opties hebben zo hun voor en nadelen. Wat mij wel weer verbaast is dat veel posters hier de nadruk enkel op efficiëntie leggen en stabiliteit blijkbaar van minder groot belang is. Dat vind ik vreemd. Stabiliteit opgeven voor snelheid vind ik een vreemde keuze. Een extra server kost misschien een paar duizend euro, maar corrupte data kan een stuk meer geld kosten.

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


Acties:
  • 0 Henk 'm!

  • Noxious
  • Registratie: Juli 2002
  • Laatst online: 19-09 22:46
Indexeerbaar zijn door zoekmachines is totaal niet relevant dus dat kan geen issue zijn ;) de databaseid + extentie zou voor filesystem dus prima zijn, om het opzoeken van andere afbeeldingen moeilijker te maken als je er eentje bekijkt (mocht het filesystem worden) zou ik daar nog een md5 van de timestamp of zoiets geks aan toe kunnen voegen, maar de request gaat sowieso altijd via een php script gebeuren voor aanpassingen.
Overigens moet ik toevoegen dat het om vrij kleine afbeeldingen gaat, maximaal 200x200 denk ik, minimaal 10x10.

Snelheid is geen issue, want inderdaad, een extra server staat er zo. Voor backups hebben beide scenario's zo hun voor en nadelen. Filesystem + kleine DB is meer portable. Een grote DB loopt altijd in sync bij backups en je hoeft minder controle te doen.

Kan iemand me nog een nadeel vertellen van het hebben van een grote database? Er zal _veel_ data in komen te zitten, maar het lost volgens mij ook een hele hoop problemen op.

Bedankt voor de alweer geweldige reacties :) _O_

Acties:
  • 0 Henk 'm!

  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
Tja, definieer _veel_ data eens...

Dbases van tig gigs zijn nog niet zo spannend ( mits je server er maar het geheugen voor heeft etc ).

Het hangt er volgens mij grotendeels vanaf of het een eigen server betreft of dat het shared hosting is. Bij shared hosting etc zal je weinig geheugen hebben waardoor het wel of niet in het geheugen kunnen hebben van de dbase een verschil kan maken...

Simpel gezegd, groot is geen argument tegen een dbase, in de dagelijkse business zijn er genoeg dbases die boven tig gig uitgaan.

Acties:
  • 0 Henk 'm!

  • Noxious
  • Registratie: Juli 2002
  • Laatst online: 19-09 22:46
De eerste test gaat op een virtuele server draaien maar een dedicated server is al beschikbaar, dat is niet zo'n probleem.
Ik weet niet of het hebben van huge MySQL databases nog problemen geeft icm het gebruikte filesystem, verder zou ik zo snel geen nadelen weten. In eerste instantie was ik van mening dat filesystem makkelijker zou zijn voor beheer, maar het kan ook juist negatief werken uiteraard.

Acties:
  • 0 Henk 'm!

  • T-MOB
  • Registratie: Maart 2001
  • Laatst online: 21:51
Je moet opletten dat MySQL standaard een limiet van 4GB kent voor table size. Daarnaast kun je problemen krijgen met je query-lengte als je grote bestanden in je database gaat zetten. Als je de MySQL server niet zelf beheerd kan dat een lastig probleem zijn (of als je software ontwikkelt die portable moet zijn).

Verder ken ik voornamelijk voordelen van bestanden in een database: de boel is makkelijker sync te houden met backups, transacties, referenties, etc...

Regeren is vooruitschuiven


Acties:
  • 0 Henk 'm!

  • Kwastie
  • Registratie: April 2005
  • Laatst online: 19-09 10:42

Kwastie

Awesomeness

Janoz schreef op donderdag 07 mei 2009 @ 10:26:
[...]

Onzin. Waar denk je dat 'data' in database voor staat?
Ik gaf alleen aan dat het opslaan binaire data in een database niet aan te raden is. Omdat je er er namelijk qua performance op achteruit gaat en je database ook groter word. Alleen de pointer opslaan zou namelijk een stuk efficiënter zijn.

When I get sad i stop being sad and be awesome instead


Acties:
  • 0 Henk 'm!

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

Janoz

Moderator Devschuur®

!litemod

Kwastie schreef op zondag 10 mei 2009 @ 22:42:
[...]

Ik gaf alleen aan dat het opslaan binaire data in een database niet aan te raden is.
En ik geef alleen maar aan dat het afraden onzin is. Het is een heel legitieme keuze die serieuze overwogen zou moeten worden.
Omdat je er er namelijk qua performance op achteruit gaat en je database ook groter word.
De vraag is hoeveel dat uitmaakt. Lees deze thread nog eens door. Er zijn meer aspecten dan enkel efficiëntie om rekening mee te houden.
Alleen de pointer opslaan zou namelijk een stuk efficiënter zijn.
Vaak wordt het BLOB type op exact deze manier geïmplementeerd binnen de database software. Zoveel scheelt het dus helemaal niet.

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


Acties:
  • 0 Henk 'm!

  • Noxious
  • Registratie: Juli 2002
  • Laatst online: 19-09 22:46
T-MOB schreef op donderdag 07 mei 2009 @ 12:09:
Je moet opletten dat MySQL standaard een limiet van 4GB kent voor table size. Daarnaast kun je problemen krijgen met je query-lengte als je grote bestanden in je database gaat zetten. Als je de MySQL server niet zelf beheerd kan dat een lastig probleem zijn (of als je software ontwikkelt die portable moet zijn).

Verder ken ik voornamelijk voordelen van bestanden in een database: de boel is makkelijker sync te houden met backups, transacties, referenties, etc...
Aah dankje :) da's wel eentje om op te letten dus. Ik beheer 'm gelukkig zelf ;)
Kan het nog een voordeel hebben om PostgreSQL te gebruiken? Ik kan op het moment die keuze maken aangezien de server waar het op gaat draaien nog fresh 'n clean is ;)

Acties:
  • 0 Henk 'm!

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

Janoz

Moderator Devschuur®

!litemod

Ik heb even lopen zoeken naar die 4GB limiet, maar voor zover ik kan vinden was dat niet een beperking van MySQL, maar van het onderliggende filesystem:

http://dev.mysql.com/doc/refman/5.0/en/full-table.html

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


Acties:
  • 0 Henk 'm!

  • Noxious
  • Registratie: Juli 2002
  • Laatst online: 19-09 22:46
Gelukkig maar, dacht al dat ik in het verleden wel eens grotere databases had gehad op een vergelijkbare server.
Dat zal met ext4 dus geen probleem worden ;) bedankt!
Pagina: 1