Te veel CPU gebruik
Een website die ik gemaakt hebt ik gehost bij een redelijk bekende hosting. Nu kreeg ik vandaag een e-mail, dat een bepaald script 50% CPU gebruikt van de MySQL-server.
Wat kan ik als oplossing gebruiken? De query is:
Code (php)
1
SELECT *, naam.id as pers_id, plaatsen.naam as plaatsnaam, MID(geboortedatum,7,4) as gjaar FROM naam, plaatsen WHERE achternaam REGEXP '^(achternaam)$' && voornaam like '%' AND naam.plaats = plaatsen.id AND ((MID(geboortedatum,7,4) <= 2000 AND MID(geboortedatum,7,4) >= 1880) OR (MID(geboortedatum,1,4) <= 2000 AND MID(geboortedatum,1,4) >= 1880)) AND geboortedatum != ''
Er is vast en zeker een beter en snellere manier voor deze query. Waar waarschijnlijk de meeste CPU vreter zit is: MID(geboortedatum,1,4)
De query haalt uit drie of soms vier verschillende tabellen zijn gegegens.
Steffan
Gewijzigd op 01/01/1970 01:00:00 door Steff an
SELECT
ster,
naam.id AS pers_id,
plaatsen.naam AS plaatsnaam, MID(geboortedatum,7,4) AS gjaar
FROM
naam,
plaatsen
WHERE
achternaam REGEXP '^(achternaam)$'
&&
voornaam LIKE '%'
AND naam.plaats = plaatsen.id
AND ((MID(geboortedatum,7,4) <= 2000
AND MID(geboortedatum,7,4) >= 1880)
OR (MID(geboortedatum,1,4) <= 2000
AND MID(geboortedatum,1,4) >= 1880))
AND geboortedatum != ''
ik snap het renamen niet waarom noem je de tabellen niet gewoon zo? Renamen doe je met name bij functies als SUM() en COUNT() ed En je vraagt alles met * dat neemt ook veel rekenkracht van de CPU
Gewijzigd op 01/01/1970 01:00:00 door Klaasjan Boven
Dit heb ik gedaan, omdat ik bij het maken van de tabellen niet nagedacht heb over dubbele namen. Dus 'naam' komt 2 keer voor, in twee tabellen.
Zo krijg je toch bij elke naam alle plaatsen?
EDIT ik zie het zo voor me dat je bij elke naam weet welke plaats erbij hoort dus dat in de tabel namen een veld voorkomt met plaat_id.
en in de tabel plaatsen komt deze natuurlijk ook voor en je voegt iets toe aan je QUERY als:
AND
plaatsen.plaats_id=namen.plaats_id
Gewijzigd op 01/01/1970 01:00:00 door Klaasjan Boven
SELECT *, naam.id as pers_id, plaatsen.naam as plaatsnaam, MID(geboortedatum,7,4) as gjaar FROM naam, plaatsen WHERE achternaam REGEXP '^(achternaam)$' && voornaam like '%' AND naam.plaats = plaatsen.id AND ((MID(geboortedatum,7,4) <= 2000 AND MID(geboortedatum,7,4) >= 1880) OR (MID(geboortedatum,1,4) <= 2000 AND MID(geboortedatum,1,4) >= 1880)) AND geboortedatum != ''
Je hebt gelijk het staat er wel in. Dan blijft alleen de * over
- De achternaam regexp verwijderd, Jelmer zei dat dit een CPU vreter is.
- MID(geboortedatum...) is verwijderd.
Ook heb ik wat 'parse time' testen gedaan. Voor deze aanpassingen was de gemiddelde parse tijd vijf seconden, na deze aanpassingen ligt deze tijd ver onder de één seconde.
Edit:
De tijd loopt weer erg voor 8-9 minuten
Gewijzigd op 01/01/1970 01:00:00 door Steff an
@Steffan ik zie niet dat Jelmer dat zei LOL
/server irc.chat4all.org
/join #phphulp
:P:P
Verder gebruik je de * operator die, zoals gezegd, niet aan te raden is. De MID funktie op een datum loslaten is ook niet slim. Er zijn in MySQL heel handige datumfuncties die je beter kunt gebruiken. Zie de handleiding.
De operator * zal ik veranderen.
En wat betreft die datum functies, dat is nu wat lastiger. Dat datums worden namelijk opgeslagen als varchar, maar verander ik nu ook.
Misschien verander ik de hele database-structuur wel, maar daar moet ik eens goed voor gaan zitten. Dat doe ik niet in deze hitte.
Gewijzigd op 01/01/1970 01:00:00 door Steff an
Steffan:
De datums worden namelijk opgeslagen als varchar, maar verander ik nu ook.
Datums sla je op als een DATE, of als een DATETIME veld. Als je een datum als een string opslaat, kan MySQL er helemaal niets meer mee.
@JAN voor de OR gebruikt hij haakjes toch?
Nu was ik toch eigenlijk wel benieuwd naar het verschil tussen =, LIKE, MATCH AGAINST en REGEXP. Misschien weer tijd voor een van jouw befaamde preformance-testjes Jan?
/me vindt ze ronduit geweldig!
Inderdaad:
((MID(geboortedatum,7,4) <= 2000 AND MID(geboortedatum,7,4) >= 1880) OR (MID(geboortedatum,1,4) <= 2000 AND MID(geboortedatum,1,4) >= 1880))
Maar zo rekent hij wel 4keer MID uit.
Er staat het volgende in:
achternaam REGEXP '^(achternaam)$' && voornaam like '%'
Waarom gebruik je hier && en op alle andere plaatsen AND? En wat heeft get voor zin om like '%' neer te zettten, want zo haalt hij alles op, onafhankelijk van wat er wel of niet in de voornaam staat.
Edit: Het kan zijn dat bij NULL de rij niet geslecteerd word...
Gewijzigd op 01/01/1970 01:00:00 door Zero Dead
achternaam REGEXP '^(achternaam)$'
achternaam = achternaam
Dat staat er eigenlijk volgensmij.
En die voornaam like % kan er idd ook uit.
@Roy
achternaam REGEXP '^(achternaam)$'
is omdat dat (twee)achternaam een echte ingevulde achternaam is, die ook wildcards kan bevatten.
Edit:
Topic kan dicht
Gewijzigd op 01/01/1970 01:00:00 door Steff an
Als vaste bezoeker moet je weten dat wij hier niets sluiten...
Quote:
Arjan, mag die nu wel dicht? :P