[PHP] Live gegevens uit de database weergeven

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • endness
  • Registratie: Maart 2006
  • Laatst online: 21:00
Voor een bepaald script moeten er elke seconde ("live" zou nog beter zijn), gegevens uit de database gehaald worden. Met wat AJAX is het met inmiddels gelukt om dit iedere seconde te doen, maar aangezien er dan elke seconde een query uitgevoerd moet worden, lijkt dit me totaal niet dataverkeer-effectief.

Ik zat te denken aan een idee dat iedereen een soort live "database" heeft die wordt geopend zodra je op de site komt. Alle gegevens worden daarin geladen, en zodra een gebruiker iets wijzigt, wordt het in die "database" opgeslagen, waarna het gelijk weer getoond wordt voor de andere gebruikers. Database is hier misschien niet het goede woord, maar ik hoop dat het idee zo duidelijk is.

Het is écht nodig om elke seconde (of sneller) nieuwe gegevens binnen te krijgen, en niet om de 5 seconden. Dan is het hele idee namelijk weg.

Alvast bedankt!

Acties:
  • 0 Henk 'm!

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

NMe

Quia Ego Sic Dico.

Je zou een cachebestandje aan kunnen maken met daarin de gegevens die je beschikbaar wil hebben. Bij elke pagina die opgevraagd wordt controleer je dan de laatste wijzigingstijd van dat cachebestandje, en als dat bestand ouder is dan een seconde (of welke andere waarde die je maar wil), dan haal je de data opnieuw op en zet je het in dat bestand neer. Mocht het cachebestand wel nieuwer zijn dan 1 seconde, dan ga je gewoon aan de slag met de data in dat bestand en laat je je database met rust.

Voor een niet zo drukke site betekent het alsnog een query voor elk request; voor een site met 1200 views per minuut breng je het aantal queries terug van 1200 naar maximaal 60. ;)

'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!

  • ppx17
  • Registratie: December 2007
  • Laatst online: 22-08 18:09
In je database de update tijden bijhouden en bij een AJAX aanvraag alleen de gegevens updaten die sinds de laatste aanvraag veranderd zijn lijkt mij het meest logisch? Hoef je niet elke keer je hele database over te gooien maar krijg je wel zo snel mogelijk alle veranderingen binnen.

edit:
Gaat wijzigings tijd niet per seconde? Als je per seconde data veranderd zal dat waarschijnlijk a-synchroon lopen, waardoor je regelmatig of data dubbel krijgt, of geen data krijgt denk ik. :X
SoaDmaggot schreef op dinsdag 16 december 2008 @ 17:47:
@ ppx17: dan doe je dus nog steeds elke seconde per gebruiker een query sturen?
Ja in principe wel, vergeet niet dat SQL gebouwd is om snel je data op te pakken van het filesystem / memory cache, waar cache file's alleen sneller zijn als je echt grote selects en joins uitvoert.

Misschien is het een idee om je cache bij te houden in een in-memory tabel, heeft MySQL in ieder geval een tabel type voor, houd hem snel en je hoeft niet je 'grote' tabel uit te lezen.

[ Voor 64% gewijzigd door ppx17 op 16-12-2008 17:50 ]

40D | 8 | 50 | 100 | 300


Acties:
  • 0 Henk 'm!

  • Cartman!
  • Registratie: April 2000
  • Niet online
Wat NMe zegt maar dan iets simpeler. Je update de cachefile op het moment dat iemand gegevens wijzigt, je spreekt dus altijd de cachefile gewoon aan. Zo heb je alleen de queries nog van mensen die updaten.

Acties:
  • 0 Henk 'm!

  • PeterSelie
  • Registratie: December 2002
  • Laatst online: 18-09 14:19
@ ppx17: dan doe je dus nog steeds elke seconde per gebruiker een query sturen?

Acties:
  • 0 Henk 'm!

  • Patriot
  • Registratie: December 2004
  • Laatst online: 19:24

Patriot

Fulltime #whatpulsert

Het lijkt me handig om het zo te doen: Bij het in de database schrijven zet je naast je data in de database een simpel .txt bestand op de server met daarin timestamp van dat moment. Je laat de browser vervolgens met AJAX checken of die timestamp in dat bestand groter is dan de timestamp van het moment dat je voor het laatst data hebt ontvangen. Als dat het geval is, dan ga je over op een AJAX request waarin je de oude timestamp (van het moment waarop je het laatst data ontving) meestuurt. Dat bestand kan dan de data sinds die timestamp uitpoepen.

Mocht dit een AJAX-based chat zijn, dan is het eventueel te overwegen om het interval enigszins variabel te maken. Je laat hem bijvoorbeeld 30 keer elke seconde checken, heeft hij alle 30 keren geen update ontvangen dan ga je om de twee seconden checken. Ontvangt hij weer 30 keer niets, dan ga je per 3 seconden checken. Je gaat zo door tot een max van bijvoorbeeld een interval van 10 seconden. Dat zorgt voor een lagere load bij inactiviteit in de chat. Dit is natuurlijk ook bij andere dingen te implementeren, niet alleen bij een chat.

Acties:
  • 0 Henk 'm!

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 06-09 00:37

curry684

left part of the evil twins

Patriot: dat is dus niet handig, in dit soort situaties ga je serverside wachten. Oftewel je vangt de request, en zolang er geen request is doe je serverside een sleep/poll/sleep/poll/etc. Op die manier beperk je de roundtrips en webserver overhead enorm - hou wel rekening met de HTTP 1.1 simultaneous connection limit waar IE6+7 nogal strikt in zijn, en je na een seconde of 15 alsnog een keer een 'no updates' terug moet sturen om timeouts te voorkomen.

Je kunt dan tevens met triggerfiles gaan werken om de belasting op je DB helemaal te nihiliseren, waarbij de request die een insert of update uitvoert een tempfile toucht. De pollers gaan vervolgens pas de DB in zodra de mtime van de triggerfile nieuwer is dan hoe ze hem kennen.

Afhankelijk van de complexiteit van je verhaal (en of mensen al of niet custom queries kunnen openzetten) is Cartman's idee ook realistisch.
ppx17 schreef op dinsdag 16 december 2008 @ 17:43:
vergeet niet dat SQL gebouwd is om snel je data op te pakken van het filesystem / memory cache, waar cache file's alleen sneller zijn als je echt grote selects en joins uitvoert.
Onzin, local file access wint het per definitie van connecten naar je database en wachten tot die je query een keer gecompiled heeft en uitgezocht of hij die data toevallig nog in memory heeft. Webserver-based caching wint op alle punten behalve feitelijk weten of er iets veranderd is.

[ Voor 38% gewijzigd door curry684 op 16-12-2008 18:02 ]

Professionele website nodig?


Acties:
  • 0 Henk 'm!

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

NMe

Quia Ego Sic Dico.

Cartman! schreef op dinsdag 16 december 2008 @ 17:46:
Wat NMe zegt maar dan iets simpeler. Je update de cachefile op het moment dat iemand gegevens wijzigt, je spreekt dus altijd de cachefile gewoon aan. Zo heb je alleen de queries nog van mensen die updaten.
Ah, uiteraard. Ik zit zelf even vast in een tunnelvisie dankzij een project waarin twee applicaties gebruik maken van dezelfde database (een hel, werkelijk waar :X ), vandaar dat mijn suggestie wat raar overkomt. :P

'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!

  • ppx17
  • Registratie: December 2007
  • Laatst online: 22-08 18:09
@Patriot:
Houd je dan voor elke seconde een nieuwe textfile bij met alle update's van die seconde? Of overschrijf je update's in de textfile wanneer ze ouder worden als een seconde? (Betekend dat je elke keer je textfile mag parsen en oude records weg mag halen). En als je ze maar 1 seconde in textfile bewaard, wat gebeurd er dan als een client een netwerk timeout krijgt en bijvoorbeeld na 2 seconde pas update, dan mist hij update's. Lijkt me ook geen ideale situatie.

40D | 8 | 50 | 100 | 300


Acties:
  • 0 Henk 'm!

  • PeterSelie
  • Registratie: December 2002
  • Laatst online: 18-09 14:19
@ ppx17: Volgens Patriot zijn idee wordt er dus een timestamp opgeslagen in de tekstfile bij update van data in de DB.. Als deze timestamp hoger is dan de timestamp van de laatste update die wordt weergegeven is er dus een file aangepast en moeten er nieuwe records opgehaald worden uit de DB.

[ Voor 49% gewijzigd door PeterSelie op 16-12-2008 18:04 ]


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Ik zou me eerst eens gaan afvragen of PHP en een webpagina dan wel het juiste middel zijn om je doel te bereiken; sowieso heb je eigenlijk alleen maar een pull-mechanisme tot je beschikking in een webpagina (op wat mislukte en gehandicapte (faux) push-implementaties na) en zou je veel beter naar sockets kunnen kijken en bijvoorbeeld een applet/flash-dinges/of whatever waarmee je live kunt communiceren of misschien is een winforms of andere client-applicatie oplossing wel mogelijk.

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • endness
  • Registratie: Maart 2006
  • Laatst online: 21:00
RobIII schreef op dinsdag 16 december 2008 @ 18:24:
Ik zou me eerst eens gaan afvragen of PHP en een webpagina dan wel het juiste middel zijn om je doel te bereiken; sowieso heb je eigenlijk alleen maar een pull-mechanisme tot je beschikking in een webpagina (op wat mislukte en gehandicapte (faux) push-implementaties na) en zou je veel beter naar sockets kunnen kijken en bijvoorbeeld een applet/flash-dinges/of whatever waarmee je live kunt communiceren of misschien is een winforms of andere client-applicatie oplossing wel mogelijk.
Klinkt allemaal erg leuk, maar daar weet ik verder helemaal niks van. PHP is eigenlijk de enige scripttaal die ik nog enigszins beheers, AJAX heb ik ook al met hulp van anderen moeten doen...

De oplossing van NMe gecombineerd met die van Cartman! lijkt mij de beste, maximaal 60 requests per minuut is wel te doen voor praktisch elke server. Is het ook mogelijk om de gegevens live uit het tekstbestand te halen? Of moet ik dat met AJAX oplossen, en dus om de seconde gaan werken?

Acties:
  • 0 Henk 'm!

  • Cartman!
  • Registratie: April 2000
  • Niet online
Vergeet niet dat het 60 requests zijn per minuut per gebruiker dus met 10 gebruikers zit je al op 600. Zelfs al heb je enkele textfiles om te benaderen (je vraagt of dat kan, probeer het gewoon eerst eens) dan zou dat een aardige load met zich meebrengen.

Acties:
  • 0 Henk 'm!

  • endness
  • Registratie: Maart 2006
  • Laatst online: 21:00
Als je ze kan "streamen" vanuit het tekstbestandje zijn het er sowieso maar 60 per minuut. Elke gebruiker gebruikt dan hetzelfde bestandje, en het wordt elke seconde gerefreshed vanuit de database. Of heb ik het hier mis? :)

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 00:27

.oisyn

Moderator Devschuur®

Demotivational Speaker

endness schreef op dinsdag 16 december 2008 @ 18:52:
[...]


Klinkt allemaal erg leuk, maar daar weet ik verder helemaal niks van. PHP is eigenlijk de enige scripttaal die ik nog enigszins beheers, AJAX heb ik ook al met hulp van anderen moeten doen...
Tijd om daar wat aan te doen dus :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Snake
  • Registratie: Juli 2005
  • Laatst online: 07-03-2024

Snake

Los Angeles, CA, USA

RobIII schreef op dinsdag 16 december 2008 @ 18:24:
Ik zou me eerst eens gaan afvragen of PHP en een webpagina dan wel het juiste middel zijn om je doel te bereiken; sowieso heb je eigenlijk alleen maar een pull-mechanisme tot je beschikking in een webpagina (op wat mislukte en gehandicapte (faux) push-implementaties na) en zou je veel beter naar sockets kunnen kijken en bijvoorbeeld een applet/flash-dinges/of whatever waarmee je live kunt communiceren of misschien is een winforms of andere client-applicatie oplossing wel mogelijk.
+ dat een db standaard niet notified als er iets veranderd is...

Dus dat moet in de client ook nog worden geimplementeerd: notify de andere clients dat er iets veranderd is.

Going for adventure, lots of sun and a convertible! | GMT-8


Acties:
  • 0 Henk 'm!

  • Cartman!
  • Registratie: April 2000
  • Niet online
endness schreef op dinsdag 16 december 2008 @ 19:24:
Als je ze kan "streamen" vanuit het tekstbestandje zijn het er sowieso maar 60 per minuut. Elke gebruiker gebruikt dan hetzelfde bestandje, en het wordt elke seconde gerefreshed vanuit de database. Of heb ik het hier mis? :)
Ja, per gebruiker. Het blijft toch echt voor elke user een 60 keer per minuut een eigen hit op de server hoor ;) en elke seconde refreshen hoeft dus niet als je mn eerste bericht had gelezen...

[ Voor 8% gewijzigd door Cartman! op 16-12-2008 19:50 ]


Acties:
  • 0 Henk 'm!

  • Patriot
  • Registratie: December 2004
  • Laatst online: 19:24

Patriot

Fulltime #whatpulsert

curry684 schreef op dinsdag 16 december 2008 @ 17:58:
Patriot: dat is dus niet handig, in dit soort situaties ga je serverside wachten. Oftewel je vangt de request, en zolang er geen request is doe je serverside een sleep/poll/sleep/poll/etc. Op die manier beperk je de roundtrips en webserver overhead enorm - hou wel rekening met de HTTP 1.1 simultaneous connection limit waar IE6+7 nogal strikt in zijn, en je na een seconde of 15 alsnog een keer een 'no updates' terug moet sturen om timeouts te voorkomen.
Huh? Ik zeg niet dat je een constante verbinding open moet houden naar dat bestand. Ik bedoel gewoon dat je dat bestand gaat pollen ipv een PHP-file die steeds een query uitvoert. Zie het zo:
  1. wegschrijven.php schrijft "boe" naar de database, bovendien schrijft deze de huidige timestamp naar timestamp.txt
  2. Er komt een client online. Deze stuurt een AJAX-request naar timestamp.txt en heeft nu een timestamp.
  3. De client heeft nog geen timestamp, dus deze kun je als zijnde 0 beschouwen. De client vergelijkt nu de timestamp uit het bestand met 0, de timestamp uit het bestand is hoger dus gaat hij gegevens opvragen.
  4. De client stuurt een request via AJAX naar gegevensopvragen.php en geeft daarbij de oude timestamp door (niet de zojuist in timestamp.txt opgevraagde timestamp, die bewaart hij nog even).
  5. Gegensopvragen.php ziet dat "boe" in de database staat, en dat deze een timestamp heeft die hoger is dan de timestamp opgestuurd door de client en stuurt dit naar de client
  6. De client ontvangt de gegevens en print deze. De timestamp die bij stap twee uit timestamp.txt kwam, stelt de client nu in als recentste timestamp met data.
  7. De client gaat verder met het pollen van timestamp.txt
Als wegschrijven.php nu "blaat" naar de database zou schrijven, en een nieuwe timestamp naar timestamp.txt, dan komt de client die tegen. De client stuurt de oude timestamp terug naar de server, die ziet dat de timestamp van "boe" niet groter is dan maar de timestamp van "blaat" wel, en zo stuurt deze alleen "blaat".

Uiteraard moet je even een limiet stellen aan het aantal rows die je de client geeft bij een timestamp van 0, omdat je anders na een dagje elke minuut een bericht versturen een boel data in één keer naar de client aan het versturen bent. Terwijl hoogstwaarschijnlijk slechts een deel relevant is (het nieuwste deel).

Dat is dus een mogelijke oplossing. Het blijft een lompe oplossing, maar het werkt wel. Bovendien is de load relatief laag.

Acties:
  • 0 Henk 'm!

  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
Weet niet hoeveel clients je verwacht, maar als je per sec wil updaten dan zou ik toch nog eens gaan kijken naar curry's idee van serverside wachten op een update of een bijna browser-timeout.
3600 hits per uur per client is leuk voor je statistieken, maar als jij geen updates hebt zijn dit 3600 nutteloze ajax-hits die wel de performance van je server aantasten.

Als jij 300 concurrent clients hebt dan neem ik aan dat jij echt niet je server-side wil upgraden ( want 1,000,000 hits per uur ) zonder als jij 1 nieuws bericht per dag plaatst.
Laat je server dus een sleep doen van 15 sec zolang je geen antwoord binnenkrijgt.Scheelt je 15x je load zolang je niets update.

Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Patriot schreef op dinsdag 16 december 2008 @ 19:53:
[...]


Huh? Ik zeg niet dat je een constante verbinding open moet houden naar dat bestand. Ik bedoel gewoon dat je dat bestand gaat pollen ipv een PHP-file die steeds een query uitvoert. Zie het zo:
...
Sorry, maar je suggestie heeft enkel nadelen tov de 3 eerder genoemde bruikbare taktieken: reads cachen (cartman), roundtrips verminderen/uitstellen response tot nuttig (Curry) en pushen ipv pullen (RobIII).

{signature}


Acties:
  • 0 Henk 'm!

  • endness
  • Registratie: Maart 2006
  • Laatst online: 21:00
Gomez12 schreef op dinsdag 16 december 2008 @ 21:44:
Weet niet hoeveel clients je verwacht, maar als je per sec wil updaten dan zou ik toch nog eens gaan kijken naar curry's idee van serverside wachten op een update of een bijna browser-timeout.
3600 hits per uur per client is leuk voor je statistieken, maar als jij geen updates hebt zijn dit 3600 nutteloze ajax-hits die wel de performance van je server aantasten.

Als jij 300 concurrent clients hebt dan neem ik aan dat jij echt niet je server-side wil upgraden ( want 1,000,000 hits per uur ) zonder als jij 1 nieuws bericht per dag plaatst.
Laat je server dus een sleep doen van 15 sec zolang je geen antwoord binnenkrijgt.Scheelt je 15x je load zolang je niets update.
Het gaat hier niet om nieuwsberichten oid, maar echt iets wat elke seconde móet updaten (zoals ook vermeld in de startpost). Wat het precies is hou ik liever nog even voor mezelf.

Het meest efficiënte zou in mijn opzicht een cache (tekstfile) zijn die elke seconde wordt bijgewerkt. Hier staat dus alle actuele database-informatie in. Elke gebruiker leest die cache uit (als ik Cartman! begrijp kan dit zonder refreshen, al dan niet met AJAX (?)), en krijgt zo dus de actuele gegevens op zijn/haar beeldscherm. Uiteraard laten we hem alleen updaten als er daadwerkelijk mensen op de site zijn.

Je krijgt dan weliswaar 60 query's naar de database per minuut, maar dat is een stuk minder dan de 60*aantal bezoekers per minuut.

@Cartman!, ik kan uit je eerste post niet halen of het nou wel of zonder refresh kan, excuses daarvoor. Ook al moet het mét refresh, dan is het alsnog server-vriendelijker om de gegevens uit een txt file te halen in plaats van uit de database.

In iedergeval bedankt voor het meedenken allemaal!

Acties:
  • 0 Henk 'm!

  • Cartman!
  • Registratie: April 2000
  • Niet online
Zal het nogmaals proberen uit te leggen:

- Je genereert txt files met de data (per id bijv., ik weet niet wat voor data t is)
- Je update de txt file alleen als er een update is in de db (dus niet elke seconde want de content blijft toch gelijk)
- Je roept met JS die txt files op zodat je geen db call hoeft te doen

Voorkomen dat elke user dus 60 hits per minuut genereert voorkom je hiermee niet en dat kan sowieso niet echt met polling (pull). Sowieso denk ik dat je browser snel zal gaan memory leaken door al die requests achter elkaar maar dat is weer een ander verhaal.

Zoals RobIII al aanhaalt kun je beter kijken naar een oplossing die werkt met push ipv. pull. Dat je dit niet kunt nog weet ik, maar je gaat jezelf, de client en de server enorm nakken met 60 hits per user per minuut heb ik t idee.

edit:
Verder kan ik er echt niet bij dat iets elke seconde moet updaten en dat je hier geen 5 van kunt maken (liefst nog minder frequent). Zonder dat we hier weten waar het om gaat zullen we dit ook blijven zeggen... probeer het anders te omschrijven zonder "prijs te geven" waar het daadwerkelijk om gaat.

[ Voor 15% gewijzigd door Cartman! op 16-12-2008 22:58 ]


Acties:
  • 0 Henk 'm!

  • Patriot
  • Registratie: December 2004
  • Laatst online: 19:24

Patriot

Fulltime #whatpulsert

Voutloos schreef op dinsdag 16 december 2008 @ 21:59:
[...]
Sorry, maar je suggestie heeft enkel nadelen tov de 3 eerder genoemde bruikbare taktieken: reads cachen (cartman), roundtrips verminderen/uitstellen response tot nuttig (Curry) en pushen ipv pullen (RobIII).
Oh?

Reads cachen: Iedere seconde alles wat gecached is sturen kost meer bandbreedte dan iedere seconde een timestamp ophalen en af en toe de gegevens ophalen. De verschillen worden kleiner naarmate het systeem actiever is, maar mijn systeem heeft weinig nadelen ten opzichte van deze manier. Wellicht is een combinatie handiger door te cachen en mijn systeem te gebruiken. Het is dan alleen de vraag of de query + alleen de nieuwe gegevens handiger is dan alle gegevens inclusief de nieuwe gegevens.

Roundtrips verminderen/uitstellen: Curry zegt zelf dat dat niet handig is omdat het protocol daar niet voor is gemaakt. Dat is meteen ook het punt bij de volgende oplossing, dat is van een héél andere aard dan werken met javascript en PHP via HTTP. De betere oplossingen voor het achterliggende probleem zijn inderdaad via andere dingen (zoals bijvoorbeeld een Java applet), maar de middelen daarvoor zijn er niet altijd. Ik kan natuurlijk wel net zoals veel mensen iedere keer weer ontsteken in een preek over de betere middelen, maar daar heb ik geen zin in. Er is niets mis met die preek hoor, omdat het voorkomt dat veel mensen fouten maken, maar ik heb geen zin om hem constant op te dreunen :).
Pagina: 1