[PHP][MySQL] veel simpele of weinig grote query's en hoe?

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • TygeR
  • Registratie: Oktober 2000
  • Laatst online: 06-02 16:23
Beste Tweakers,

Ik ben vaak bezig met het ontwerpen van php/mysql/ajax gebaseerde CMS systemen, meestal gewoon als hobby. Nu maak ik zelf vaak gebruik van relatief simpele SQL query's bijvoorbeeld:
Een query om alle pagina's weer te geven voor het menu,
Een query om de Artikelen die zich in een bepaalde pagina bevinden te laden,
Een query voor elk artikel om de bijbehorende data binnen te halen.
Soms gebruik ik zelfs wel eens een query om alleen een username aan de hand van een userID te achterhalen. Op deze manier wil het echter wel eens voorkomen dat een frontpage zo'n 15 query's nodig heeft en een complexere pagina bijvoorbeeld forum kan wel eens zo'n 50 query's laden.
Simpel om te computen voor de SQL server dacht ik altijd, ik heb hier verder ook nooit echt performance problemen mee gemerkt, normaal laad een pagina met 40 query's op de server die ik gebruik binnen enkele honderdsten van een seconde. Nu lees ik echter zo hier en daar op een forum dat mensen zich al zorgen maken als het aatal query's per pagina boven de 8 uit komt en sommigen zweren zelfs bij max 3 query's per pagina.
Mijn eerste vraag is aan de experts is dit echt nodig? wat gaat er mis als ik mijn methode blijf volgen?

Vervolgens zat ik te bedenken, als ik het aantal query's wil reduceren dan worden de query's aardig complex, en ook de output wordt enorm. Ik maak bijvoorbeeld voor een normale pagina gebruik van een database structuur in boom vorm van 4 lagen diep. Als mij dan aan de limit van 3 query's per pagina probeer te houden zou ik bijvoorbeeld met een volgende query kunnen werken om alle pagina data te laden:

SELECT L1.name,L1.title,L1.blaawathever,L2.name,L2.data,L3.name,L3.data,L4.name,L4.data FROM L1 INNER JOIN (L2 INNER JOIN (L3 INNER JOIN L4 ON L4.l3ID = L3.l3ID) ON L3.l2ID = L2.l2ID) ON L2.l1ID = L1.l1ID WHERE L1.l1ID = xx AND L4.language = NL;

Bijvoorbeeld dus (normaal gebruik ik wel fatsoenlijke namen voor de tabellen ;-) )
Deze query levert een enorme resultset op waarin ik niet echt een makkelijke manier weet om er snel data uit te halen in php behalve dan met for lussen te gaan scannen. Deze oplossing lijkt mij niet de manier om query's te minderen.

Mijn vragen hierbij zijn:
1: Wat is wijsheid? heeft het zin om met grote complexe query's het aantal terug te dringen?
2: Is er een manier om in PHP makkelijker deze grote resultsets te doorzoeken?
3: Hoe kijken jullie tegen mijn vraag aan? als ik totaal op het verkeerde spoor zit laat me dan weten hoe het wel kan (of geef in ieder geval een hint in de goede richting).

Overigens ben ik niet van plan om bestaande CMS systemen te gaan gebruiken om dit probleem op te lossen, niet omdat ze niet goed zijn, maar omdat de kern van deze vraag hem in het ontwikkelen zelf zit en niet in de oplossing om snel een site te lanceren.

Acties:
  • 0 Henk 'm!

  • Sjoerd
  • Registratie: December 2003
  • Niet online
Eigenlijk geen antwoord op je topic maar uit ervaring weet ik dat je indexen goed leggen voor veel meer performance winst geeft dan een paar minder query's.

Ik zelf probeer grote query's overigens wel te cachen (indien mogelijk). Maar het is niet zo dat ik iets heb van max zoveel query's...

Modelbouw - Alles over modelbouw, van RC tot diorama


Acties:
  • 0 Henk 'm!

  • Pete
  • Registratie: November 2005
  • Laatst online: 07-09 17:51
Wat betreft de query die je geeft: Ik zou proberen het aantal queries "in een loop" (dus voor het ophalen van "childs" bijvoorbeeld) proberen te reduceren tot 1 query. Één mogelijkheid hiervoor kun je vinden op crisp's blog en een andere op sitepoint

Verders ben ik het met Sjoerd eens, goede indexen is veel belangrijker dan het verminderen van je queries. En caching kan wonderen doen.

petersmit.eu


Acties:
  • 0 Henk 'm!

  • daaan
  • Registratie: Maart 2000
  • Laatst online: 04-09 13:13

daaan

Brandweer Zoutkamp

Ik denk niet dat er een vaste regel voor het maximale aantal queries is. Ik vind de aantallen die jij noemt (40 á 50 ) wel érg hoog. Maar als het een zeer complexe pagina is, kun je zeker op een hoog aantal uitkomen.

Ik denk dat de posts die je leest door een nogal fanatieke groep wordt gemaakt, ik zou me er ook niet te veel aan storen.

Verder wat Sjoerd en Pete hierboven al aangeven, indexes en caching :).

One's never alone with a rubber duck.


Acties:
  • 0 Henk 'm!

  • MueR
  • Registratie: Januari 2004
  • Laatst online: 14:53

MueR

Admin Tweakers Discord

is niet lief

Minder queries proberen te bouwen puur en alleen om het maken van minder queries zou ik niet doen in ieder geval.

[ Voor 7% gewijzigd door MueR op 21-01-2009 15:36 ]

Anyone who gets in between me and my morning coffee should be insecure.


Acties:
  • 0 Henk 'm!

  • Eddy Dean
  • Registratie: November 2007
  • Laatst online: 19:16
Als er geen performance probleem is zou ik vooral geen optimalisaties doen die je code complexer maken, je kunt je tijd beter besteden aan nieuwe features, en dingen waar de gebruiker wel iets van merkt.

Acties:
  • 0 Henk 'm!

  • Yoozer
  • Registratie: Februari 2001
  • Laatst online: 03-08 17:53

Yoozer

minimoog

TygeR schreef op woensdag 21 januari 2009 @ 14:54:
Op deze manier wil het echter wel eens voorkomen dat een frontpage zo'n 15 query's nodig heeft
Cachen, cachen, cachen. Denk je dat de reviews, pricewatch e.d op de t.net frontpage ook elke keer opnieuw worden opgehaald? :)
en een complexere pagina bijvoorbeeld forum kan wel eens zo'n 50 query's laden.
Wat geef je weer op zo'n complexe pagina? Statistieken?

Het is niet erg dat er veel queries worden gedaan of dat ze lang duren, als je maar zeker er van kunt zijn dat die pagina 1 keer per maand wordt gebruikt door een manager of zo om statistieken op te halen, in plaats van duizenden keren per uur door reguliere visitors.
Ik maak bijvoorbeeld voor een normale pagina gebruik van een database structuur in boom vorm van 4 lagen diep.
Hoe vaak per keer wordt die boom opgebouwd of gewijzigd? Wat geeft 'ie weer?

teveel zooi, te weinig tijd


Acties:
  • 0 Henk 'm!

  • MueR
  • Registratie: Januari 2004
  • Laatst online: 14:53

MueR

Admin Tweakers Discord

is niet lief

Eddy Dean schreef op woensdag 21 januari 2009 @ 15:43:
Als er geen performance probleem is zou ik vooral geen optimalisaties doen die je code complexer maken, je kunt je tijd beter besteden aan nieuwe features, en dingen waar de gebruiker wel iets van merkt.
En dan vervolgens tegen de tijd dat je performance problemen krijgt zoveel features te optimaliseren hebben dat het onbegonnen werk is? De noemen wij op kantoor de Hyves-methodeTM, en dat is een slecht idee. Wat je wel kan doen is kijken waar je veel gebruik van maakt (record van ingelogde user en zijn rechten bijvoorbeeld) en die gewoon in je sessie inladen.

[ Voor 4% gewijzigd door MueR op 21-01-2009 15:48 ]

Anyone who gets in between me and my morning coffee should be insecure.


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Ik ben vooral benieuwd naar de datastructuur van een site van iemand die blijkbaar weet hoe joins werken en tóch 50 queries nodig heeft voor een pagina. :o

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • DEiE
  • Registratie: November 2006
  • Laatst online: 18-09 15:15
Ik lees dat je een aparte query gebruikt om alle artikelen op te halen, en vervolgens een query gebruikt om de data per artikel te laden. Dit is een voorbeeld waar je één query van zou kunnen maken, en dat kan (bij bijvoorbeeld een pagina met 100 artikelen) al een aantal queries schelen. Bij een forum is dit principe natuurlijk ook mogelijk, wordt de query waarschijnlijk wel wat langer.

Ook geven een aantal databasesystemen (zoals phpmyadmin of de MySQL query browser) aan hoe lang erover gedaan wordt om een query uit te voeren. Zo kan je ook kijken of het de moeite waard is om je query's te vervangen van veel kleine naar enkele grote.

Acties:
  • 0 Henk 'm!

  • MBV
  • Registratie: Februari 2002
  • Laatst online: 20-09 22:44

MBV

Als je serieuze performance nodig hebt zal je de database op een andere server draaien dan de webserver (o.a. omdat een database-server andere eisen heeft dan een webserver). Dan merk je iets in de round-trip-time: per query moet er een pakketje gestuurd worden, uitgepakt worden aan de andere kant, en resultaat terug gestuurd worden. Dan gaat het aantal queries per pagina echt tellen. Op dezelfde machine zal het weinig uitmaken.

Ik zou zeggen dat er een gulden middenweg is: zodra queries te moeilijk worden, wordt het lastiger qua onderhoud en lastiger voorspellen hoe lang ze duren. De situatie die jij schetst in het begin is dan weer het andere uiterste :)

Acties:
  • 0 Henk 'm!

  • storeman
  • Registratie: April 2004
  • Laatst online: 12:59
De geneste resultaten ophalen via PHP is niet de beste manier, queries moeten al zo goed als vast staan.

Waar ik aan zou denken is een database functie die dit voor je genereert. Hierdoor kun je deze logica mooi met database logica oplossen in plaats van in je PHP code, deze maakt zich alleen druk op wat te doen met de data, niet de opbouw ervan.

Ik weet niet of je bekend bent met dergelijke functies, maar het is zeker de moeite waard om er eens naar te kijken. Je hebt immers maar 1 query vanuit PHP, in je DBMS gebeurd veel meer, maar daar hoef je je maar 1 maal druk om te maken.

"Chaos kan niet uit de hand lopen"


Acties:
  • 0 Henk 'm!

  • Eddy Dean
  • Registratie: November 2007
  • Laatst online: 19:16
MueR schreef op woensdag 21 januari 2009 @ 15:47:
[...]

En dan vervolgens tegen de tijd dat je performance problemen krijgt zoveel features te optimaliseren hebben dat het onbegonnen werk is? De noemen wij op kantoor de Hyves-methodeTM, en dat is een slecht idee. Wat je wel kan doen is kijken waar je veel gebruik van maakt (record van ingelogde user en zijn rechten bijvoorbeeld) en die gewoon in je sessie inladen.
Nee, je moet natuurlijk je code zo maken dat het goede performance heeft, en blijkbaar heeft de ts dat (gezien de gemiddelde laadtijden die hij aangeeft). Iets dat niet kapot is moet je niet willen repareren. Als te verwachten valt dat iets problemen op gaat leveren is het kapot, maar ik weet niet of dat hier het geval is.

De pagina laadt in 'enkele honderdsten van een seconde'. Dan is mijn mening: niet klagen, het werkt prima zo. Als 'enkele honderdsten' 5/100e sec is, dan mag de load (in views per seconde) rustig 10 keren zo groot worden zonder dat er sprake is van een echt performance probleem. Is zo'n groei aanemelijk? Verbeteren nu het nog relatief weinig werk is, anders gewoon laten zoals het is.

Daarbij is het misschien niet mogelijk om het verder te optimaliseren door de query's te joinen, omdat het betekend dat php werk over moet nemen van de database server, en dat misschien averechts werkt. Cachen is dan een betere oplossing.

Met andere woorden, beslis zelf of de performance zo te laag is, en optimaliseer dan als het nodig blijkt. Als je twijfelt over een oplossing die nu goed lijkt te werken is het wel verstandig om dit goed te encapsulaten (wie weet daar een Nederlands woord voor?), zodat het makkelijk te veranderen is als het nodig blijkt.

Acties:
  • 0 Henk 'm!

  • TygeR
  • Registratie: Oktober 2000
  • Laatst online: 06-02 16:23
NMe schreef op woensdag 21 januari 2009 @ 15:48:
Ik ben vooral benieuwd naar de datastructuur van een site van iemand die blijkbaar weet hoe joins werken en tóch 50 queries nodig heeft voor een pagina. :o
Dit heb ik denk ik met name te danken aan het feit dat ik veel les heb gegeven in object georiënteerd programmeren. Waardoor ik snel geneigd ben om ergens een object van te maken. Zo heb ik bevoorbeeld een feature object (dit bouwt zeg maar een weer te geven artikel op). deze objecten maken gebruik van een database connector class en laad vervolgens zelf de gegevens die hij nodig heeft om het artikel op te bouwen via de database connector uit de database. Elk artikel is dus een eigen instantie van de Feature class en runt zijn eigen query's via de database connector. Als ik het artikel wil weergeven hoef ik alleen maar het object aan te maken en te vragen om het feature in pseudo code zoiets:

$feature1 = new Feature($database, $featureID);
echo $feature1->getHTML();

Daaraan vooraf gaat een query waaruit alle te laden features voor een bepaalde pagina moeten blijken.
Het kan voorkomen dat er actief feature is (dan wordt php code uit de database geladen, die een ander object aanmaakt en vervolgens weergeeft) ook deze kan query's uitvoeren. zoals bijvoorbeeld een plugin die de database gebruikt. Zo heb ik bijvoorbeeld een forum object wat ik op die manier makkelijk in een willekeurige site kan gebruiken.

[ Voor 17% gewijzigd door TygeR op 21-01-2009 19:22 ]


Acties:
  • 0 Henk 'm!

  • Yoozer
  • Registratie: Februari 2001
  • Laatst online: 03-08 17:53

Yoozer

minimoog

TygeR schreef op woensdag 21 januari 2009 @ 19:11:
Elk artikel is dus een eigen instantie van de Feature class en runt zijn eigen query's via de database connector. Als ik het artikel wil weergeven hoef ik alleen maar het object aan te maken en te vragen om het feature in pseudo code zoiets:

$feature1 = new Feature($database, $featureID);
echo $feature1->getHTML();
Ik weet dat het pseudocode is, maar doet die Feature in z'n eigen klasse dan elke keer de verbinding met de db opengooien en dan weer dichtsmijten? (en met die logica, waarom de database meegeven als parameter als in 9 van de 10 gevallen je toch met 1 db te maken hebt - of je moet natuurlijk alleen maar verwijzen naar de db resource)
(dan wordt php code uit de database geladen
Is dit nou wel zo'n verstandig idee? Je sleurt en pleurt een hoop uit de db wat je niet een-twee-drie kan wijzigen (en belangrijker, waar je niet zomaar in kan zoeken) en in het ergste geval zet je een achterdeur open voor iemand die die code weet uit te voeren met een exploit.
Zo heb ik bijvoorbeeld een forum object wat ik op die manier makkelijk in een willekeurige site kan gebruiken.
Maar zo heb je zelf dus het wiel opnieuw uitgevonden terwijl die tijd wellicht beter besteed was aan het installeren en skinnen van een reeds werkende oplossing, want het zit er dik in dat je eigen forum qua features achterloopt op de populaire gratis oplossingen. Magoed, noem nog eens een stel andere queries op die op je 50-queries pagina staat :).

[ Voor 6% gewijzigd door Yoozer op 21-01-2009 19:34 ]

teveel zooi, te weinig tijd


Acties:
  • 0 Henk 'm!

  • Saven
  • Registratie: December 2006
  • Laatst online: 18:37

Saven

Administrator

Nu ga ik wel een klein beetje offtopic, maar ik zie dat mensen het hier hebben over 'querys cachen'. Ik heb een beetje zitten googlen en voor zover ik begrijp is dit gewoon een optie in MySQL die je kunt in schakelen. Wellicht hebben de meeste hosters die sowieso al aan staan?
Of sla ik hier de plank finaal mis?

Acties:
  • 0 Henk 'm!

  • TygeR
  • Registratie: Oktober 2000
  • Laatst online: 06-02 16:23
Even een reactie op Yoozer:

Elk feature object gebruikt een en dezelfde database connector, deze beheert de connectie. Per pageload wordt er dus maar 1 keer verbinding gemaakt met de database en aan het eind wordt deze weer 1 keer verbroken.

Daarnaast beheert de database connector de beveiliging. Alle rijen die er toe doen in de database hebben een unix achtige rechten structuur. Het is voor een plugin alleen mogelijk om via de connector een verbinding te maken (of je moet de database username en wachtwoord weten maarja.. dan is kraken via phpmyadmin veel makkelijker). Deze database connector zal alleen maar data weergeven en schrijven waarvoor de huidige gebruiker van de site bevoegd is.

Overigens zit er wel een CMS editor in de site die ook de phpCode die in de database voor een feature is opgeslagen makkelijk wijzigt, echter is het php gebruik uit de database in praktijk vaak alleen een call naar een object wat als file is opgeslagen (hiervoor is dus geen verdere query nodig).

Gratis forums zijn er wel, maar ik vindt de meeste niet echt mooi en makkelijk aan te passen aan het ontwerp van de site... En zoals in mijn top-post beschreven de gimmick zit hem er voor mij niet in om zo snel mogelijk een website op internet te knallen, maar om zelf het geheel te ontwikkelen (zo houd ik ook mijn eigen kennis up to date, programmeer kennis niet alleen kennis van bestaande modules).
Magoed, noem nog eens een stel andere queries op die op je 50-queries pagina staat :).
Een voorbeeld is bijvoorbeeld de hoofd pagina in het forum hierop staan alle forums inclusief de een snapshot van de post topic (per laatste post per forum 1 query) vervolgens geeft het forum weer wie de laatste topic heeft geplaatst, echter staat in de post zelf alleen het uID. de routine getUsername($uID) maakt hiervan een gebruikersnaam ten koste van een hele simpele query. als je dus een 20 forums (forum->topic->post model) hebt staan op je forum zijn dat al 40 query's.

[ Voor 29% gewijzigd door TygeR op 21-01-2009 19:50 ]


Acties:
  • 0 Henk 'm!

  • _js_
  • Registratie: Oktober 2002
  • Laatst online: 18-08 21:31
Dat kan dus heel makkelijk in 1 query. Of het ook sneller is moet je zelf maar even meten. In ieder geval post->user kun je joinen, dat scheelt al de helft van de queries en zal niet langzamer zijn dan nu.

Acties:
  • 0 Henk 'm!

  • GlowMouse
  • Registratie: November 2002
  • Niet online
Saven schreef op woensdag 21 januari 2009 @ 19:38:
Nu ga ik wel een klein beetje offtopic, maar ik zie dat mensen het hier hebben over 'querys cachen'. Ik heb een beetje zitten googlen en voor zover ik begrijp is dit gewoon een optie in MySQL die je kunt in schakelen. Wellicht hebben de meeste hosters die sowieso al aan staan?
Of sla ik hier de plank finaal mis?
Nee, die cache is niet zo efficiënt omdat hij veel te vaak geleegd wordt (zoek de details maar op). Veelal wordt voor een oplossing gekozen die de output van een functie die data ophaalt ergens op te slaan, wanneer die functie niet zo snel is. In die langzame functie kun je kijken of er een gecachete versie bestaat, en zoja, de rest van de functie over te slaan. Dat is weinig ingrijpend en snel geïmplementeerd, en heeft meestal prima resultaat. De cache kun je bewaren in een MySQL-tabel (primary key lookups zijn snel), op het filesystem of in een daarvoor ingerichte memcached.

Acties:
  • 0 Henk 'm!

  • Saven
  • Registratie: December 2006
  • Laatst online: 18:37

Saven

Administrator

GlowMouse schreef op woensdag 21 januari 2009 @ 20:49:
[...]

Nee, die cache is niet zo efficiënt omdat hij veel te vaak geleegd wordt (zoek de details maar op). Veelal wordt voor een oplossing gekozen die de output van een functie die data ophaalt ergens op te slaan, wanneer die functie niet zo snel is. In die langzame functie kun je kijken of er een gecachete versie bestaat, en zoja, de rest van de functie over te slaan. Dat is weinig ingrijpend en snel geïmplementeerd, en heeft meestal prima resultaat. De cache kun je bewaren in een MySQL-tabel (primary key lookups zijn snel), op het filesystem of in een daarvoor ingerichte memcached.
Jeps dat had ik al door inderdaad. Ik gebruik nu een (redelijk 'vieze') vorm van serverside cache gebruiken. Ik sla de output met html en al op. Dat ik alleen maar die file hoef te includen en er staat een heel menu zegmaar :P.

Maar als ik jou goed begrijp kan ik dus bijvoorbeeld een query fetchen, die fetch serializen en in een database stoppen. Vervolgens unserializen uit de DB en die (array in dit geval) te gaan foreachen. Ik gebruik namelijk PDO FetchAll() wat dus een array teruggeeft. :)?

Acties:
  • 0 Henk 'm!

  • MBV
  • Registratie: Februari 2002
  • Laatst online: 20-09 22:44

MBV

@TS: ik denk dat je, als je een 'overdreven nette' OO structuur aan wilt houden, je het beste een factory kunt gebruiken die alles in 1x opvraagt, voor de veelvoorkomende patronen. Stel, je hebt een winkel met op de voorpagina de top-10 verkochte producten met de hoogste marge. Dan maak je een factory method die een array van 10 Producten oplevert, met alle details er al in. Voor de 'lastige' gevallen waarbij je niet kan voorspellen of je alles nodig hebt, houd je je huidige methode aan, voor de voorspelbare en/of veelvoorkomende gevallen kan je dan zoiets gebruiken.

En over cachen: bij PHP kan je het beste de complete pagina cachen, op basis van de (relevante) parameters. Bij veel pagina's is 75% van de oproepen semi-statisch. Bij een grote winkel met web'shop' heb ik de load gehalveerd door de CSS en JS files niet alleen server-sided te laten cachen, maar ook de goede caching-headers te geven. Dat werkte zo goed, dat ik de voorpagina cachen uit heb laten staan (er zat een bug in, dus tijdelijk uitgezet, en nooit meer naar omgekeken :X)

[ Voor 29% gewijzigd door MBV op 21-01-2009 23:13 ]


Acties:
  • 0 Henk 'm!

  • MueR
  • Registratie: Januari 2004
  • Laatst online: 14:53

MueR

Admin Tweakers Discord

is niet lief

TygeR schreef op woensdag 21 januari 2009 @ 19:40:
Een voorbeeld is bijvoorbeeld de hoofd pagina in het forum hierop staan alle forums inclusief de een snapshot van de post topic (per laatste post per forum 1 query) vervolgens geeft het forum weer wie de laatste topic heeft geplaatst, echter staat in de post zelf alleen het uID. de routine getUsername($uID) maakt hiervan een gebruikersnaam ten koste van een hele simpele query. als je dus een 20 forums (forum->topic->post model) hebt staan op je forum zijn dat al 40 query's.
Oh, je bedoelt:
SQL:
1
2
3
4
5
6
7
SELECT f.forumid, f.forumnaam, f.description, p.postid, t.topicid, t.title, u.username, u.userid
FROM forum f
LEFT JOIN post p ON p.postid = f.lastpostid
LEFT JOIN topic t ON t.topicid = p.topicid
LEFT JOIN user u ON u.userid = p.userid
WHERE f.visible = 1
ORDER BY f.sortorder ASC

Hele lijst gedaan, 1 query.
Eddy Dean schreef op woensdag 21 januari 2009 @ 16:19:
Nee, je moet natuurlijk je code zo maken dat het goede performance heeft, en blijkbaar heeft de ts dat (gezien de gemiddelde laadtijden die hij aangeeft). Iets dat niet kapot is moet je niet willen repareren. Als te verwachten valt dat iets problemen op gaat leveren is het kapot, maar ik weet niet of dat hier het geval is.
Op het moment geeft de TS 40 queries te doen op de tabel user, om bij elk forum de username van de laatste poster (ook 40 queries voor de posts natuurlijk). Dan is je app niet performant, dan heb je gewoon geluk dat de server niet druk is. 40 keer een query voor iets wat ook makkelijk met een JOIN gedaan kan worden is namelijk niet performant en mag je wel degelijk optimaliseren, als je het uberhaupt optimaliseren kan noemen. Common sense klinkt beter.

[ Voor 32% gewijzigd door MueR op 21-01-2009 23:32 ]

Anyone who gets in between me and my morning coffee should be insecure.


Acties:
  • 0 Henk 'm!

  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
Op zich zou ik inderdaad wel het aantal query's terug dringen door een aantal factory's aan te maken.
Maar die max 3 query's per pagina vind ik echt overtrokken onzin. Dat soort rigoreuze harde regels zorgt imho alleen maar voor onleesbare query's die meer fouten in de hand werken dan ze performance oplossen.

Acties:
  • 0 Henk 'm!

  • TygeR
  • Registratie: Oktober 2000
  • Laatst online: 06-02 16:23
MueR schreef op woensdag 21 januari 2009 @ 23:28:
[...]

Oh, je bedoelt:
SQL:
1
2
3
4
5
6
7
SELECT f.forumid, f.forumnaam, f.description, p.postid, t.topicid, t.title, u.username, u.userid
FROM forum f
LEFT JOIN post p ON p.postid = f.lastpostid
LEFT JOIN topic t ON t.topicid = p.topicid
LEFT JOIN user u ON u.userid = p.userid
WHERE f.visible = 1
ORDER BY f.sortorder ASC

Hele lijst gedaan, 1 query.


[...]

Op het moment geeft de TS 40 queries te doen op de tabel user, om bij elk forum de username van de laatste poster (ook 40 queries voor de posts natuurlijk). Dan is je app niet performant, dan heb je gewoon geluk dat de server niet druk is. 40 keer een query voor iets wat ook makkelijk met een JOIN gedaan kan worden is namelijk niet performant en mag je wel degelijk optimaliseren, als je het uberhaupt optimaliseren kan noemen. Common sense klinkt beter.
Zwart wit gezien (in theorie) kom je hier wel mee weg, echter is de realiteit iets complexer. Mede in verband met security en andere toegangsregels (gebruikers, groepen, clubs en annoniem). Ik ben overigens wel weer een stuk wijzer geworden door dit topic en denk dat het inderdaad nu de tijd is om code te optimaliseren en om het aantal query's terug te dringen. Ik ben er momenteel wel achter dat ik alleen met complexere query's hier niet in slaag (te veel voorwaarden), maar met een relatief simpele SQL Function (Thanks MySQL 5.0+) om de acces policy naa te leven kom ik ineens een heel eind.

Bedankt iedereen voor de waardevolle reacties.

Acties:
  • 0 Henk 'm!

  • MueR
  • Registratie: Januari 2004
  • Laatst online: 14:53

MueR

Admin Tweakers Discord

is niet lief

Dan heb je dus 1 query nodig om te bepalen welke fora iemand mag zien, en bak je in de pseudoquery die ik je gaf een WHERE forumid IN (zichtbare fora). Klaar is TygeR. Niet moeilijker maken dan het is.

Anyone who gets in between me and my morning coffee should be insecure.


Acties:
  • 0 Henk 'm!

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06 13:31

drm

f0pc0dert

TygeR: misschien is het voor jou ook wel nuttig om eens te kijken naar een goeie object/relational mapper tool. Doctrine en Propel zijn hier voorbeelden van, voornamelijk Doctrine heeft een hele handige feature die de dingen die jij wilt heel goed kan optimizen. (Toch objecten maken van items die je uit een gejoinde query ophaalt).

Het heeft wel iets overhead natuurlijk, maar je kunt m.i. altijd beter cachen dan in de core van je systeem premature gaan optimaliseren.

PS: MueR, flauw: left joins zijn veel duurder dan inner joins. Over het algemeen heb je aan de frontend helemaal geen left joins nodig voor content; lege dingen zijn toch niet interessant ;)

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz


Acties:
  • 0 Henk 'm!

  • MueR
  • Registratie: Januari 2004
  • Laatst online: 14:53

MueR

Admin Tweakers Discord

is niet lief

Psst drm:
Wel als het om een forumlijst gaat. Je wil fora namelijk wel zichtbaar hebben, ook als het leeg is :)

Alternatief daarvoor is een losse query waarin je de laatste posts met bijbehorende info ophaalt, voor alle fora op de lijst (dus niet 1 query per forum, dat is idioot). Vervolgens in een array stoppen met het forum id als key en je kan er zo bij.

[ Voor 52% gewijzigd door MueR op 23-01-2009 16:03 ]

Anyone who gets in between me and my morning coffee should be insecure.


Acties:
  • 0 Henk 'm!

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06 13:31

drm

f0pc0dert

MueR:
Psst drm:
Wel als het om een forumlijst gaat. Je wil fora namelijk wel zichtbaar hebben, ook als het leeg is :)
ook posts zonder users en topics zonder posts ...? :Y)

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz


Acties:
  • 0 Henk 'm!

  • MBV
  • Registratie: Februari 2002
  • Laatst online: 20-09 22:44

MBV

Ja, als de gebruikers gebanned zijn maar je de discussies niet wilt verstoren door posts weg te halen :P

Acties:
  • 0 Henk 'm!

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06 13:31

drm

f0pc0dert

you didn't think that through ....

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz


Acties:
  • 0 Henk 'm!

  • MueR
  • Registratie: Januari 2004
  • Laatst online: 14:53

MueR

Admin Tweakers Discord

is niet lief

Niet muggenziften drm :P Dit was een "2 minuten net voor ik naar bed ging" query :P

Anyone who gets in between me and my morning coffee should be insecure.


Acties:
  • 0 Henk 'm!

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06 13:31

drm

f0pc0dert

Ok :*, back on topic then :)

drm:
TygeR: misschien is het voor jou ook wel nuttig om eens te kijken naar een goeie object/relational mapper tool. Doctrine en Propel zijn hier voorbeelden van, voornamelijk Doctrine heeft een hele handige feature die de dingen die jij wilt heel goed kan optimizen. (Toch objecten maken van items die je uit een gejoinde query ophaalt).

Het heeft wel iets overhead natuurlijk, maar je kunt m.i. altijd beter cachen dan in de core van je systeem premature gaan optimaliseren.
Ben benieuwd of TS hier iets aan heeft?

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz


Acties:
  • 0 Henk 'm!

  • TygeR
  • Registratie: Oktober 2000
  • Laatst online: 06-02 16:23
drm schreef op vrijdag 23 januari 2009 @ 22:50:
Ok :*, back on topic then :)

Ben benieuwd of TS hier iets aan heeft?
Ik moest eerst even lezen wat ORM was hoor ;-), dit zou inderdaad wel een mogelijkheid zijn om bijvoorbeeld compleet geïnstantieerde objecten te cachen in de database.

Inmiddels heb ik echter wat uitgebreidere performance tests gedaan, en heb ik geconstateerd dat er voornamelijk veel query's uit het permission systeem kwamen en dan met name in het opvragen van zaken als adminLevels, relatie met de owner, en de isInGroup vraag. Deze aanvragen worden nu per pageload afgehandeld in plaats van per aanvraag. Waardoor ik nu op een gemiddelde pagina terug ben gelopen van 64 tot 10 query's met een flinke boost in page load time, van 10-20 honderdste tot 3 honderdste. Deze 54 query's bevatte allemaal één join en kennelijk stoort dit de performance nogal. De pagina waar het forum object in aanwezig is (een complexere pagina) laad nu met ongeveer 50 query's echter zijn dit allemaal platte query's zonder joins en laad nog steeds binnen de 6 honderdsten. Als ik deze (even permissie systeem uitgeschakeld) laad met één enkele gejoinde query (vrij simpele join, ongeveer gelijk aan die van MeuR maar dan meer inner joins en slechts een left join) dan loopt de pagina laad tijd op naar 20 honderdsten. De server waar mijn site op draait is tegelijkertijd mysql server als webserver en tot nu toe lijkt het er op dat met een dergelijke set-up meer kleine query's sneller werkt dan minder grotere/(relatief complexere) query's. Ik kan me goed voorstellen dat dit anders wordt als de mysql server en de webserver op een andere machine draaien.

Momenteel ben ik voornamelijk bezig met het cachen van de resultaten en dit geeft een goede performance boost! De rede dat ik met name hier nu tijd in stop is omdat dit logischerwijs met bijde set-ups even veel performance wint. bedankt voor deze tip, eigenlijk heel logisch maarja soms hebben we allemaal wel eens last van tunnelvisie. En dan zijn er gelukkig altijd wel tweakers die je er weer uit kunnen helpen.

Momenteel kan ik ongeveer uitgaan van een pagina laad tijd van minder dan 5 honderdste, als ik dan even grof reken kan de server dan 1200 pageviews per minuut aan (qua processor en geheugen belasting). Dit ligt ruim boven het verwachte aantal pageviews op de sites. Ik zou bij 120 pageviews per minuut al zeer tevreden zijn :D :P .

Acties:
  • 0 Henk 'm!

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06 13:31

drm

f0pc0dert

Ik wees je even op die O/R mappers omdat je het prettig vindt om (netjes) object georienteerd te werken en bereid bent daar ook een deel van de performance voor in te leveren (dat herken ik wel). Dan is een goeie O/R mapper heel fijn om te hebben.
Als ik deze (even permissie systeem uitgeschakeld) laad met één enkele gejoinde query (vrij simpele join, ongeveer gelijk aan die van MeuR maar dan meer inner joins en slechts een left join) dan loopt de pagina laad tijd op naar 20 honderdsten
Hoe staat het er dan met je indexes voor? Want zo'n enorme increase vind ik wel veel als je je indexes goed hebt staan.

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz

Pagina: 1