Op mijn website (Scoort.nu) kunnen voetbalteams een eigen website beheren. Voor elk team worden de gegevens van KNVB.nl automatisch geupdate. Ik krijg echter de laatste paar dagen steeds de melding "MySQL server has gone away" bij het updaten van de gegevens. Nou heb ik er wat naar gezocht en nou blijkt mijn MySQL server overbelast te zijn, klopt dat?
Mijn script werkt op de volgende manier:
- Teams worden ingeladen
- Per team wordt eerst de stand en daarna het programma geupdate via aparte functies.
- Aan het eind worden alle waarden verwijderd (mysql_free_result).
Weet iemand hoe ik ervoor kan zorgen dat met één keer draaien alle teams worden afgegaan en dat ik tóch niet de server overbelast? Alvast bedankt.
gebruik je LIMIT in je query? Zo niet, zou dat al een deel kunnen verhelpen
edit: die free result, is dat persé nodig? volgens mij niet echt
edit 2:
php.net schreef:
mysql_free_result() only needs to be called if you are concerned about how much memory is being used for queries that return large result sets. All associated result memory is automatically freed at the end of the script's execution.
DeviourSoul bedankt voor je hulp. Als ik LIMIT gebruik, dan kan ik toch niet met het draaien van het script in één keer de gegevens van alle teams updaten of wel ?
Overigens gebruik ik voor het veilig invoeren in de database mysql_real_escape_string(), misschien dat het daardoor zou kunnen komen. De code die ik gebruik om de stand te updaten is: Plaatscode: 23746
De code van het programma en de resultaten is vergelijkbaar aan die van de stand.
Dus heeft iemand een idee? Of is dat van DeviourSoul toch de oplossing voor mijn probleem?
Denk er wel aan dat wanneer je integers in de database zet, je geen ' ' eromheen zet.
De database ziet het dan als string en dat werkt nou eenmaal langzamer.
Let er verder gewoon goed op dat je keys gebruikt en integers voor vergelijken (userID's, geen usernames), alhoewel dat laatste meestal al wel wordt gedaan.
Ik heb zojuist de enkele aanhalingstekens bij de integers verwijderd zoals Medieval zei. Als mijn script het trouwens inleest van knvb.nl, ziet het die getallen dan eigenlijk wel als integers? Of maakt dat niet uit?
Hmm alles via INSERT statements doen is ook erg traag.
Hoeveel records insert je met 1 zo'n actie ongeveer?
Misschien is het een idee om de standen op te splitsen.
De oude resultaten verplaats je naar een andere tabel en de nieuwe kan je dan uit een file inladen met sql loader. dat werk vele malen sneller omdat de database je SQL syntax dan niet hoeft te parsen.
Bovenstaande query staat in een foreach-loop die meestal 12 keer doorlopen wordt per team. Op het moment zijn het nog maar 12 teams en dus 144 query's per datasoort (stand, uitslagen, programma). Het zijn er uiteindelijk dus heel veel.
@Slipie: Eerlijk gezegd snap ik niet helemaal waarom de manier die jij geeft sneller is. Je moet namelijk de oude resultaten toch ook ergens in een andere tabel invoeren... Of werkt dat op een andere manier?
Bovendien ben ik niet echt bekend met het inladen van bestanden, maar als dat de oplossing is, kan ik het misschien wel gaan leren.
je zou met je foreach die laatste 3 regels in een $variabel kuynnen zetten die je door $variabel.="('".$waarde1a."',...)"; laat bijvullen. Dan word het nog maar 1 insert
Zoals je zelf aangeeft gaat het bij het laden van de knvb data vaak fout.
Als je de data iedere keer naar een andere tabel schrijft dan kan je dat gecontroleerd doen en zowiezo in 1 statement wat al helemaal sneller gaat dan 144 losse insert statements.
Stel je maakt een 2e tabel die noem je old en je tabel met de laatste data noem je new.
Dan krijg je de volgende query:
LOAD DATA INFILE='path naar je csvfile'
INTO TABLE new
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n';
LOADDATAINFILE='path naar je csvfile'
INTOTABLE new
FIELDS TERMINATED BY','
LINES TERMINATED BY'\n';
Maar laten we eerlijk zijn, dit zijn allemaal omwegen om de performance beter te krijgen. Het beste is om de hardware van de machine, waar je database op draait, gewoon te upgraden.
@Mediaval een beetje database kan 10tallen transacties per seconden aan.
En aan een INSERT valt niet echt veel te tunen.
Maargoed je zou ook nog een sleep in je loop kunnen stoppen.
De import duurt dan langer maar je database raakt dan niet overbelast.
Met jullie hulp kom ik er denk ik wel, daarom sowieso bedankt!
Ik ga nu proberen om eerst alle gegevens tijdens de foreach-loop in een array op te slaan. Pas als alle gegevens van dat team in de array zitten, mysql_real_escape_string() er overheen gooien en dan meteen in de database doen met een meervoudige INSERT. Zou dat kunnen helpen? Op die manier staat de mysql-connectie toch niet de hele tijd open of wel?
Edit:
Ik ben nu bezig met die meervoudige insert, maar ik kan niet vinden hoe ik een variabel aantal records INSERT... Dus een soort van while-loop in MySQL. Iemand die mij hiermee op weg kan helpen?
Om MySQL te overbelasten moet je wel meer doen dan een paarhonderd insert's per seconde...
Even een mythe ontkrachten:
Citaat:
Denk er wel aan dat wanneer je integers in de database zet, je geen ' ' eromheen zet.
De database ziet het dan als string en dat werkt nou eenmaal langzamer.
Let er verder gewoon goed op dat je keys gebruikt en integers voor vergelijken (userID's, geen usernames), alhoewel dat laatste meestal al wel wordt gedaan.
Klinkklare onzin, MySQL kijkt intern wel voor je welk type het moet worden, dat hoef je zelf niet aan te geven. Getallen worden nou eenmaal apart gelext, dat is ook de enige reden dat je getallen buiten quotes mag hebben. Niks geen verschil in snelheid, of accuraatheid.
Hey, allebei ook nog bedankt voor jullie opmerkingen. Ondanks mijn poging om de scripts te optimaliseren, krijg ik nog steeds elke keer "Mysql server has gone away". Ik heb zelfs tussen elke handeling (programma, stand en uitslagen) een sleep van 20 seconden gezet. Nu kan ik wel per team het script laten draaien, maar alle teams achter elkaar is helaas nog niet mogelijk ...
Voor elk record zijn ongeveer 6 mysql_real_escape_string()-acties nodig en per soort handeling zijn er 12 records. Zou de server dit normaal gewoon aan moeten kunnen ?
Hoe vaak wordt dat script gedraaid? Bij iedere pagina die wordt geladen? Of maar een keer als iemand wat aanmaakt? Of maar een keer per dag?
Lijkt me niet nodig om het iedere keer te updaten aangezien er meestal maar 1 wedstrijd per week is dus hoeft het maar een keer in de 7 dagen te worden geupdated.
En die knvbripper, wat ript dat allemaal? Ript dat alle data van de knvb of alleen wat je nodig hebt?
@Wimmarien: In PHPmyadmin kan ik alleen de volgende limitatie vinden die er misschien iets mee te maken zou kunnen hebben:
Citaat:
max. concurrent connections 24
Alleen wat dat precies inhoud weet ik dus niet ... Ik heb overigens een betaalde host.
@Gothmog: Het script wordt elke dag minimaal 1 keer gedraaid zodat alle gegevens van alle teams in mijn eigen database geschreven worden. Soms wijzigt de KNVB nog wel eens iets tussendoor, vandaar dat het elke dag geupdate moet worden. Maar bij één keer runnen van het script is de server al overbelast. (tenminste, ik heb aangenomen dat "Mysql server has gone away" betekent dat het overbelast is ...). Ik kan het script wel telkens handmatig voor één team laten draaien, maar dat is nog best veel werk om een paar keer per week te doen.
Overigens wordt alleen de nuttige informatie in mijn database gestopt (teams en de getallen die daarbij horen).
Wat dacht je van dit: run het script maar een keer in de 10 minuten, en update iedere 10 minuten maar een team. Zodra er meer teams komen wordt het bijv. 5 minuten.
Zo duurt het maar heel even en is het toch up to date.
Allemaal bedankt voor jullie hulp. Het werkt zoals ik al eerder zei voor één team tegelijk gewoon goed. Ik laat nu op aanraden van Gothmog het script vaker draaien, telkens voor één team. Het werkt nu goed, dus nogmaals allemaal bedankt !
mssn te laat, maar je zou met een sleep kunnen werken. 1 bestand, en dan in je while na elk team een sleep(5) kunnen zetten. Dan houd het script zelf ff een pauze en kan je server bijkomen
Hey DeviourSoul, bedankt dat je ook meedenkt. Ik heb tussen de verschillende scripts al een sleep van 15 seconden staan en helaas lukte het nog niet om alle teams up te daten .... maar toch bedankt!