PHP + MySQL, denormalisera bilder

Permalänk
Medlem

PHP + MySQL, denormalisera bilder

Tjenare!

Jag har ett litet community för skojs skull, mest för att experimentera med olika lösningar osv som sen appliceras på ett av mina lite mer seriösa projekt.

Det mesta är redan denormaliserat, inga JOINS används för forumposter tex men problemet är att jag nog skulle vilja göra samma sak för bilder.
Man kan bifoga upp till 10 bilder per foruminlägg och för att hämta dessa bilder ser queryn ut ungefär såhär:

<?php $images_query = mysql_query( "SELECT `imagename` FROM `post_images` WHERE `image_post_id` = $post_id "); while ($image_query = mysql_fetch_assoc($images_query)) { $image_query['imagename']; } ?>

Det finns just nu ca 50´000 rader i post_images databasen, tar ju inte så jättelång tid att hämta bilderna och queryn ovanför körs endast om forum inlägget har bilder.

Men ändå, känns som man kan optimera lite ändå, eftersom man ändå har en query för att hämta alla forum inlägg så tänker jag att man lika gärna kan lägga in ett forum inläggs bifogade bilder redan där så slipper man köra ännu en query för att hämta bilderna.

Tex när man skriver ett forum inlägg så kan man ju köra något i stil med:

<?php $images_query = mysql_query( "SELECT `imagename` FROM `post_images` WHERE `image_post_id` = $post_id "); while ($image_query = mysql_fetch_assoc($images_query)) { $postimages .= $image_query['imagename'] . ',' } ?>

Den skapar då en lista som ser ut något i stil med: "bild1.jpg,bild2.jpg,bild3.jpg,bild4.jpg,bild5.jpg" som man sen sparar i databasen för foruminläggen och har en kolumn som heter något i stil med "post_images" eller whatever.

Sen för att visa dom bifogade bilderna för ett visst forum inlägg så hämtar man bara $post_query['post_images'] som ger resultatet "bild1.jpg,bild2.jpg,bild3.jpg,bild4.jpg,bild5.jpg", sen kör man bara en PHP explode via "," och sen en foreach loop på det.

Vad tror ni om det? Det borde väl vara snabbare och mindre resurskrävande att göra en explode på upp till 10 bilder än att leta upp dessa bilder från databasen på varenda foruminlägg i forumtråden som har bilder?

Förstår att jag förklarar sjukt otydligt men hoppas ni hängde med på det mesta iaf

PS. Ja jag särkrev foruminlägg

Visa signatur

Hur kan syltkakor överleva i det vilda utan ögon?

Permalänk
Medlem

Av ren känsla så säger jag att det borde ju vara snabbare att dra med bilderna direkt i foruminlägget.
Antar att du bara lagrar sökvägen till bilderna ändå och inte faktiska bilden i databasen.
Så tänker mig att explode ersätter en querry och då känns det som att en querry borde vara mer resurskrävande än en explode. I och med att båda ger samma resultat.

Eftersom normalisering är till för att undvika dubletter och onödig data så ska detta nästan vara bättre, iallafall om man snackar datamängd.

Visa signatur

ASRock p67 extreme 4 | OCZ 240gb SSD + 320GB WDC + 1TB WDC GP | Intel Core i7 2600k | Nvidia Geforce GTX970 | 16gb Crucial Ballistix | Antec HC pro 1200w | Fractal define R2

Permalänk
Medlem

<?php $images_query = mysql_query( "SELECT `imagename` FROM `post_images` WHERE `image_post_id` = $post_id "); while ($image_query = mysql_fetch_assoc($images_query)) $postimages[] = $image_query['imagename']; } ?>

Och vips så slipper du en explode.

Permalänk
Medlem

Tack för svaren

Skrivet av Lofman:

Av ren känsla så säger jag att det borde ju vara snabbare att dra med bilderna direkt i foruminlägget.
Antar att du bara lagrar sökvägen till bilderna ändå och inte faktiska bilden i databasen.
Så tänker mig att explode ersätter en querry och då känns det som att en querry borde vara mer resurskrävande än en explode. I och med att båda ger samma resultat.

Eftersom normalisering är till för att undvika dubletter och onödig data så ska detta nästan vara bättre, iallafall om man snackar datamängd.

Ja precis, det är endast sökvägen som lagras i databasen, inte bilder, eller ja, det är inte ens sökvägen utan bara bildens namn som sparas, alla bilder lagras i samma mapp så hela sökvägen behövs inte sparas i databasen.

Japp, en explode på max 10 bilder, som redan hämtas med varje post inlägg bör vara snabbare än att hämta varje bild från en query. Speciellt med tanke på att flera forum inlägg per sida kan ha bilder, då sparar man endel databasanrop.

Enda nackdelen jag kommer på just nu är att i post_images databasen sparade jag även en timestamp på när en bild laddades upp, men med tanke på att bilderna laddas upp som en bifogning till foruminlägget så är det ju inte direkt jättekritiskt att spara timestampen för varje bild, går ju använda timestampen för foruminlägget om man nu i framtiden behöver det till något.

Skrivet av iXam:

<?php $images_query = mysql_query( "SELECT `imagename` FROM `post_images` WHERE `image_post_id` = $post_id "); while ($image_query = mysql_fetch_assoc($images_query)) $postimages[] = $image_query['imagename']; } ?>

Och vips så slipper du en explode.

Njae? Det jag skall göra är alltså att gå bort från ovanstående, jag skall INTE köra ännu en query för att hämta bilderna, det är det jag vill komma bort ifrån.
Ovanstående query används endast för att samla ihop bilderna och lägga in dom i raden för forum inlägget såhär:

(ej den riktiga databasen, slängde bara ihop det som ett exempel så man ser själva tanken med det)

Queryn för att hämta bilderna skall alltså inte användas för att faktiskt hämta bilderna sen när forum inlägget visas, queryn används endast en gång när forum inlägget skapas för att samla ihop alla bilder och lägga in det som en sträng i "post_images" som synes i min bifogade bild.

Poängen är alltså, man hämtar ju ändå forum inläggen, har man alla bilderna som förknippas med ett foruminlägg i en sträng som ovan så slipper man ju göra ytterliggare en query för att hämta alla bilder från post_images, nu följer ju alla bilder med direkt i forum_post queryn istället, blir alltså som sagt ingen extra query för själva forum bilderna.

Visa signatur

Hur kan syltkakor överleva i det vilda utan ögon?

Permalänk
Medlem

Bättre att använda nåt i stil med json_encode() då. Vet att det ska finnas nån annan funktion som eventuellt kan göra det bättre, kommer dock inte ihåg vad den heter.

Permalänk
Medlem

Om du endast kör egna projekt och har hög access på databasservern, så rekommenderar jag att du skapar funktioner direkt på MySQL servern.

Du tar sedan en "Inner Join" och en Select på den funktionen tillsammans med en where på den funktionen med den laddade forumpostens id.

Permalänk
Medlem
Skrivet av Snacker:

Bättre att använda nåt i stil med json_encode() då. Vet att det ska finnas nån annan funktion som eventuellt kan göra det bättre, kommer dock inte ihåg vad den heter.

Behöver bara hämta själva bildens namn så vet inte om json_encode ger något övertag i mitt fall men skall testa båda.

Skrivet av uykuda:

Om du endast kör egna projekt och har hög access på databasservern, så rekommenderar jag att du skapar funktioner direkt på MySQL servern.

Du tar sedan en "Inner Join" och en Select på den funktionen tillsammans med en where på den funktionen med den laddade forumpostens id.

Ditt förslag är jättebra om vill ha så dålig prestanda som möjligt.

Visa signatur

Hur kan syltkakor överleva i det vilda utan ögon?

Permalänk
Medlem
Skrivet av JesperA:

Behöver bara hämta själva bildens namn så vet inte om json_encode ger något övertag i mitt fall men skall testa båda.

Ditt förslag är jättebra om vill ha så dålig prestanda som möjligt.

Fast egentligen vill du använda en dokumentdatabas till det här. Du försöker använda en banan till att slå i en spik.

Skickades från m.sweclockers.com

Visa signatur

Kom-pa-TI-bilitet

Permalänk
Medlem
Skrivet av Teknocide:

Fast egentligen vill du använda en dokumentdatabas till det här. Du försöker använda en banan till att slå i en spik.

Skickades från m.sweclockers.com

Nej, oavsett om jag använder en SQL eller noSQL databas så går det ut på att bara hämta 1 objekt från databasen (1 inlägg inkl bilderna för inlägget = 1 objekt), istället för att hämta tex 8 objekt (1 inlägg + 7 bilder = 8 objekt), detta gäller både för SQL och noSQL (noSQL = enbart hämta 1 "dokument" istället för 8).

Och MySQL lär inte ha några som helst problem med att hämta en sträng bestående av ca 100 tecken. Varför skulle den ha problem med det menar du? Det är ju just det man lagrar i databaser (förutom int, datetime osv osv)

Visa signatur

Hur kan syltkakor överleva i det vilda utan ögon?

Permalänk
Medlem
Skrivet av JesperA:

Nej, oavsett om jag använder en SQL eller noSQL databas så går det ut på att bara hämta 1 objekt från databasen (1 inlägg inkl bilderna för inlägget = 1 objekt), istället för att hämta tex 8 objekt (1 inlägg + 7 bilder = 8 objekt), detta gäller både för SQL och noSQL (noSQL = enbart hämta 1 "dokument" istället för 8).

Och MySQL lär inte ha några som helst problem med att hämta en sträng bestående av ca 100 tecken. Varför skulle den ha problem med det menar du? Det är ju just det man lagrar i databaser (förutom int, datetime osv osv)

Jag är inte säker på vad du säger nej till men det verkar onekligen som om du är ute efter en dokumentdatabas. MySQL & co. är ju relationella databaser, det är där deras styrka ligger. Visst, du kan lagra onormaliserad data i MySQL, kokosnötter i ett bankvalv och du kan använda en banan (fryst) till att slå i spik, men det är inte så de är tänkta att användas.

Inner joins är relativt (heh) effektiva, är du verkligen säker på att det kommer bli ett problem?

Bygger på mitt svar lite;
Du kan hämta all data du behöver i ett svep genom att använda relationella funktioner i MySQL.

SELECT posts.post_id, <andra kolumner ...>, inner_query.imagecollection FROM posts INNER JOIN ( SELECT post_images.image_post_id, GROUP_CONCAT(imagename) imagecollection FROM post_images WHERE post_images.image_post_id = posts.post_id GROUP BY post_images.image_post_id) inner_query ON posts.post_id = imagequery.image_post_id

Ur "PHP-perspektiv" ser det med queryn ovan ut som om din post-tabell innehåller en kolumn där alla länkade bilder finns samlade.

Visa signatur

Kom-pa-TI-bilitet