[MySQL/PHP] - Cachen van queries

Pagina: 1
Acties:
  • 173 views sinds 30-01-2008
  • Reageer

Onderwerpen


Acties:
  • 0 Henk 'm!

  • gvanh
  • Registratie: April 2003
  • Laatst online: 02-12-2023

gvanh

Webdeveloper

Topicstarter
Hallo!

Om een website met een groot aantal bezoekers wat sneller te laten draaien heb ik een caching systeem gemaakt dat het resultaat van MySQL in een cache opslaat.

Als locatie voor de data gebruik ik een andere MySQL tabel. Het is nu zo dat de objecten die de query zelf als resultaat heeft wordt "geserialized" met PHP en vervolgens in de cache-tabel alszodanig wordt opgeslagen. Ik zie nu dat de cache-tabel snel enorme proporties aanneemt.

Als table layout gebruik ik nu het volgende:
MySQL:
1
2
3
4
5
6
7
CREATE TABLE query_cache (
  query_hash varchar(35) NOT NULL default '',
  query_data mediumtext NOT NULL,
  query_tstamp timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
  PRIMARY KEY  (query_hash),
  KEY query_tstamp (query_tstamp)
)


De query_hash is daarin een hash van de query die gecached wordt, zodat iedere unieke query tot zijn eigen cache leidt.

Zoals te zien gebruik ik nu voor de opslag van de (serialized) data een "mediumtext" veld. Is dat met het oog op de snelheid van de tabel handig? Of kan ik beter voor een BLOB-variant kiezen? De overweging om het als TEXT op te slaan is dat ik me kan herinneren dat de lengte van TEXT-velden in de tabel als variabel opslagen wordt, zodat niet voor iedere row een gefixeerde lengte wordt gereserveerd.

Overigens hoef ik dus NIET te zoeken op de inhoud van het veld.

De vraag is dus:
1. Is deze manier van cachen überhaupt raadzaam, of zijn hier slimmere/snellere oplossingen voor
2. Als het niet de slechtst denkbare optie is, is er dan een handiger veld-type om te kiezen voor de daadwerkelijke data?

Alvast veel dank voor het meedenken.

Acties:
  • 0 Henk 'm!

Verwijderd

Waarom maak je niet gebruik van MySQL's eigen query cache? Die is vrij uitgebreid en erg goed. Ook heeft MySQL andere cache functies voor bijvoorbeeld indexen enzo die handig kunnn zijn.

Acties:
  • 0 Henk 'm!

  • YopY
  • Registratie: September 2003
  • Laatst online: 13-07 01:14
Voor zover ik weet zijn geserialiseerde objecten 'gewoon' byte arrays (op het systeemniveau), en blobs zijn beter geschikt daarvoor dan mediumtexts. Ik weet niet wat handiger is, maar ik kan me voorstellen dat er meer controles en conversies en limieten op text fields zijn in vergelijking met blobs.

Qua keuze voor dit kan ik je niet verder helpen. Zelf heb ik zoiets nog niet nodig gehad in PHP, het enige wat er op lijkt is het cache systeem van vBulletin (forum software), welke posts parsed en geparsed in de database opslaat, zodat het niet opnieuw geparsed moet worden. Zelf ben ik wel bezig met een webapp, maar dan in Java. Voordeel daarvan is dat het een 'persistente' applicatie is, dus dat je objecten in het geheugen kunt houden. Er wordt ook gebruik gemaakt van een cache systeem, wat indien er teveel objecten in de cache komen de gegevens wegschrijft op de harde schijf.

Ik heb laatst hier gelezen dat er ook zo'n cache systeem voor PHP beschikbaar is; misschien kun je daar naar kijken?

Maar ja, zoals TRRoads al zei kun je misschien beter kieken naar MySQL zijn cache systeem.

Acties:
  • 0 Henk 'm!

  • LauPro
  • Registratie: Augustus 2001
  • Laatst online: 19-09 16:51

LauPro

Prof Mierenneuke®

:o

Dit is absoluut onzin. Je kan beter de gegenereerde output cachen in plain HTML files die je elke 5 minuten ververst.

Inkoopacties - HENK terug! - Megabit
It is a war here, so be a general!


Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Mysql heeft een query cache en die werkt prima, ware het niet dat hij vrij rigoreus alle gecachete queries van tabel X flusht als er een update in tabel X plaatsvindt. Aan de andere kant, de query cache data is tenminste nooit stale, en dat is echt niet triviaal om zelf beter na te bouwen.

Wat je doet is leuk om een keer gedaan te hebben, maar het is pure tijdverspilling. :+ :>

{signature}


Acties:
  • 0 Henk 'm!

Verwijderd

In de nieuwere versies is dat toch een stukje beter gemaakt dacht ik?

Meestal wordt MySQL ingezet in webservers waarbij je het write few read many principe hebt, de cache kan dan de schaalbaarheid van het geheel enorm helpen (terwijl je nog steeds gewoon een goede DB setup moet hebben met efficiente queries).

Overigens zijn er wel situaties te denken waarbij zo'n eigen cache erg handig kan zijn hoor, maar het is beter eerst te kijken naar de mogelijkheden die MySQL zelf al heeft voordat je gaat denken over een eigen cache.

[ Voor 26% gewijzigd door Verwijderd op 09-10-2007 17:08 ]


Acties:
  • 0 Henk 'm!

  • LauPro
  • Registratie: Augustus 2001
  • Laatst online: 19-09 16:51

LauPro

Prof Mierenneuke®

Verwijderd schreef op dinsdag 09 oktober 2007 @ 17:07:
Overigens zijn er wel situaties te denken waarbij zo'n eigen cache erg handig kan zijn hoor, maar het is beter eerst te kijken naar de mogelijkheden die MySQL zelf al heeft voordat je gaat denken over een eigen cache.
Misschien als pilot maar iig niet in productieomgevingen. Niet alleen omdat MySQL hier al een functie voor heeft maar omdat je juist zo'n query cache in zet om je DBMS te ontlasten, dus als je al een cache zou willen doen dan zou dit filesystem based moeten zijn.

Echter zit de query cache van MySQL in het geheugen en dat zal dus veel sneller zijn dan een filesystem kan bereiken waarschijnlijk. (Tenzij je iets lokaal weet te implementeren met een tmpfs oid.)

Inkoopacties - HENK terug! - Megabit
It is a war here, so be a general!


Acties:
  • 0 Henk 'm!

  • gvanh
  • Registratie: April 2003
  • Laatst online: 02-12-2023

gvanh

Webdeveloper

Topicstarter
Ah ... dat is interessant ... de query cache van MySQL zelf!
Stiekem was ik er eigenlijk vanuit gegaan dat de cache-functionaliteit van MySQL zelf standaard "aan" staat ... maar dat dit in dit geval gewoon onvoldoende was.

Voordat ik verder vraag over hoe ik die functionaliteit dan gebruik, zal ik eerst wel eens gaan zoeken op "MySQL cache".

Dank voor de insights!

Met betrekking tot het cachen van de HTML-pagina's zelf nog even ... dat lijkt me in dit geval lastig, omdat er allerlei onderdelen al dan niet geladen kunnen worden, afhankelijk van welke gebruiker is ingelogd. Je zou dan dus per URL en per gebruikersgroep moeten cachen ... maar zelfs dan weet je niet zeker of de pagina goed geladen is, want de gebruiker kan weer rechten hebben die afwijken van de groep. En wanneer je gaat cachen per gebruiker ... dan kun je in mijn optiek net zo goed niet cachen!

UPDATE
Net inderdaad de MySQL manual geraadpleegd over query-cache ... en dat staat inderdaad standaard aan. In dat geval helpt dat dus blijkbaar niet (afdoende). Of kan het wellicht zo zijn dat de query-cache niet werkt voor Stored Procedures?

[ Voor 12% gewijzigd door gvanh op 09-10-2007 17:43 . Reden: aanvulling ]


Acties:
  • 0 Henk 'm!

  • LauPro
  • Registratie: Augustus 2001
  • Laatst online: 19-09 16:51

LauPro

Prof Mierenneuke®

Denk eerder dat je wat tijd moet besteden aan de juiste indices en het goed afstellen van je SP's dan dat je met query caching aan de slag moet. Andere oplossing is natuurlijk hardwarematig een upgrade doen.

Inkoopacties - HENK terug! - Megabit
It is a war here, so be a general!


Acties:
  • 0 Henk 'm!

  • gvanh
  • Registratie: April 2003
  • Laatst online: 02-12-2023

gvanh

Webdeveloper

Topicstarter
Wat bedoel jij met SP's?

:?

Acties:
  • 0 Henk 'm!

  • frickY
  • Registratie: Juli 2001
  • Laatst online: 18-09 14:42
Stored Procedures.

A Practical Look at the MySQL Query Cache had je al gevonden?

[ Voor 80% gewijzigd door frickY op 09-10-2007 18:48 ]


Acties:
  • 0 Henk 'm!

  • gvanh
  • Registratie: April 2003
  • Laatst online: 02-12-2023

gvanh

Webdeveloper

Topicstarter
Ja ... had ik inderdaad gezien ... dank!

Naar aanleiding van wat je zei ben ik nu eens aan het heroriënteren op de vraag of alle queries wel gebruik maken van indices. Daarbij ben ik enorme queries eens aan het strippen tot the bare essentials en vervolgens laat ik er eens wat EXPLAIN op los.

Nu kom ik tot een heel simpel iets met de volgende query.
MySQL:
1
2
3
SELECT *
FROM ( cms_objects AS O, cms_navs AS I )
WHERE O.cms_objectID = I.objectID


De twee tabellen zijn vrij basaal en iedere row in cms_navs heeft via de primary key (bestaande uit ID en version) een relatie met de cms_objects tabel. Eigenlijk dus een foreign key ... alhoewel je die niet kan instellen in MySQL met MyISAM (toch?!).

Als ik nu een explain hierop uitvoer, dan krijg ik het volgende resultaat:
code:
1
2
3
id  select_type     table   type        possible_keys   key             key_len     ref                 rows
1   SIMPLE              I           ALL         PRIMARY                 NULL            NULL            NULL                47
1   SIMPLE              O           eq_ref  PRIMARY                 PRIMARY     4               I.objectID  1


De eerste rij geeft dus aan dat er geen key wordt gebruikt. Is dat normaal?
Hopelijk kan iemand hierover zijn licht laten schijnen.
Ik ga ondertussen voor de tigste keer de uitleg over de EXPLAIN functionaliteit lezen.

Acties:
  • 0 Henk 'm!

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

MySQL's query cache is nogal zinloos om te noemen, dat staat standaard aan maar is niet bepaald de (enige) oplossing als je veel pageviews doet. Wij hebben het zelfs uitgezet.

Ik zou overigens niet dingen in je database opslaan, maar es goed kijken naar technieken als (bij een enkele webserver) eaccelerator of APC's caching of (bij meerdere webservers) memcached. Die ontlasten dan je database meer dan je nu van plan bent. Bovendien hebben ze een groot deel van de administratie al voor je ontwikkeld (ttl's enzo) en kan je het ook gebruiken voor andere dingen dan pure query-resultaten.

Acties:
  • 0 Henk 'm!

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

gvanh schreef op dinsdag 09 oktober 2007 @ 19:35:
Daarbij ben ik enorme queries eens aan het strippen tot the bare essentials en vervolgens laat ik er eens wat EXPLAIN op los.
Zomaar de queries strippen moet je mee oppassen... je wilt tenslotte de query die je daadwerkelijk uitvoert versnellen, niet een andere. Zoek overigens uit welke queries het meeste tijd kosten (begin evt met de slow log) en/of het vaakst uitgevoerd worden, daar heb je het meeste aan om te optimaliseren.
De twee tabellen zijn vrij basaal en iedere row in cms_navs heeft via de primary key (bestaande uit ID en version) een relatie met de cms_objects tabel. Eigenlijk dus een foreign key ... alhoewel je die niet kan instellen in MySQL met MyISAM (toch?!).
Foreign key maakt de toegang niet sneller ofzo, het is enkel een constraint (die idd niet in MyISAM bestaat), maar je zou een index op het veld kunnen leggen dat je een foreign key noemt, als die er niet al is.
Overigens is MyISAM niet bepaald de meest schaalbare storage engine op het moment dat er geregeld op geschreven wordt. Voor tabellen waar zowel veel op gelezen als regelmatig geschreven wordt ben je meestal beter af met InnoDB.
De eerste rij geeft dus aan dat er geen key wordt gebruikt. Is dat normaal?
Hopelijk kan iemand hierover zijn licht laten schijnen.
Ik ga ondertussen voor de tigste keer de uitleg over de EXPLAIN functionaliteit lezen.
Je geeft geen WHERE-clause op. Dus dan moet een van de twee tabellen (bij voorkeur de kleinste, maar dat mag mysql lekker zelf bepalen) sequentieel uitgelezen worden. Daarnaast moeten records van de andere tabel erbij gezocht worden en dat gebeurd zo te zien wel via een index (de PK).

Acties:
  • 0 Henk 'm!

  • gvanh
  • Registratie: April 2003
  • Laatst online: 02-12-2023

gvanh

Webdeveloper

Topicstarter
Je geeft geen WHERE-clause op. Dus dan moet een van de twee tabellen (bij voorkeur de kleinste, maar dat mag mysql lekker zelf bepalen) sequentieel uitgelezen worden. Daarnaast moeten records van de andere tabel erbij gezocht worden en dat gebeurd zo te zien wel via een index (de PK).
Ja dat ... klinkt vrij logisch ... naar aanleiding van de EXPLAIN manual page heb ik net ook al weer even een STRAIGHT_JOIN geprobeerd op dezelfde query ... en dan zie je inderdaad dat MySQL uit zichzelf de juiste keuze heeft gemaakt met het starten met de cms_navs tabel.
Zoek overigens uit welke queries het meeste tijd kosten (begin evt met de slow log) en/of het vaakst uitgevoerd worden, daar heb je het meeste aan om te optimaliseren.
Is de "de slow log" een functionaliteit van MySQL ... of is dat onderdeel van mijn eigen te bouwen log-functionaliteit? Ik heb inderdaad vorige week zelf een Logfunctie gemaakt om alle queries te loggen inclusief de execution time. Daar ben ik al wel wat wijzer uit geworden. Ik zit er alleen een beetje mee dat op mijn testserver de queries vrij rap draaien (< 0.3 sec.) voor de allertraagste (die ook nog eens gecached wordt) ... maar dat op de LIVE server dezelfde query al snel een seconde of 10 duurt. Dat is vreselijk traag. Waar dat vandaan komt weet ik nog niet precies. In de running processes zie ik vrij veel "sleep" staan, waarbij blijkbaar wordt gewacht op andere queries, al is niet duidelijk waarop precies.

Maar gut ... 50 bezoekers tegelijk (volgens mij is het in die orde van grootte) of 1 bezoeker maakt dus de boel al werkelijk veel trager.

UPDATE:
Ah ... zojuist inderdaad slow-log functionaliteit gevonden ... dat is handig.

[ Voor 49% gewijzigd door gvanh op 09-10-2007 20:03 ]


Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
gvanh schreef op dinsdag 09 oktober 2007 @ 19:47:
even een STRAIGHT_JOIN geprobeerd op dezelfde query ... en dan zie je inderdaad dat MySQL uit zichzelf de juiste keuze heeft gemaakt met het starten met de cms_navs tabel.
Niks keuze gemaakt, dmv dat keyword dwing je mysql. ;)

Lees je aub in of zoek eerst in de mysql manual voordat je het wiel opnieuw uit vindt. Slow query log is handig heilig. Verder is het wel handig om met explain leren omgaan. Als vuistregel is het dan handig om vooral aandacht te besteden aan queries waarbij heel veel rows bekeken moeten worden, of waar er 'using filesort' of 'using temporary table' in de extra kolom staat. :)

{signature}


Acties:
  • 0 Henk 'm!

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

gvanh schreef op dinsdag 09 oktober 2007 @ 19:47:
Waar dat vandaan komt weet ik nog niet precies. In de running processes zie ik vrij veel "sleep" staan, waarbij blijkbaar wordt gewacht op andere queries, al is niet duidelijk waarop precies.
Zit er dan toevallig ook een update (of insert of delete) op die tabel tussen? Zoja, kijk es naar innodb, dat heeft wat prettigere karakteristieken voor meerdere bezoekers tegelijk.

Acties:
  • 0 Henk 'm!

  • gvanh
  • Registratie: April 2003
  • Laatst online: 02-12-2023

gvanh

Webdeveloper

Topicstarter
Ja ... ik weet inmiddels redelijk met EXPLAIN om te gaan ... uit dit verhaal begrijp ik overigens dat filesort onvermijdelijk is wanneer je wilt sorteren op verschillende kolommen.

Ik zit nu - naar aanleiding van het uitvoeren van EXPLAIN op een aantal queries - met een aantal vragen.
In één query gebruik ik > om alleen rijen te selecteren die na een bepaalde datum zijn opgeslagen. Op de betreffende kolom staat een index. Maar die wordt niet gebruikt. Ik heb ook al geprobeerd om er een onredelijk groot waarde bij te halen, zodat ik BETWEEN kan gebruiken, maar nog steeds wordt de key niet gebruikt (ook niet voor een RANGE) ... dat snap ik niet zo goed. Maakt het daarvoor nog uit dat ik de datums heb opgeslagen als seconden sinds EPOCH en niet als DATETIME?

Verder gebruik ik een hoop sub-queries ... die sowieso niet gebruik lijken te kunnen maken van een index. Daarbij is - generaliserend - het idee ongeveer:

[code=mysql]
SELECT (
/* algemene query op 2 tabellen */
) AS tmp WHERE ( SELECT hasPermission(<userID>, tmp.<uniqueID>, <operation>) ) = 1
[/mysql]
Daarbij is hasPermission dan een stored procedure die afhankelijk van de parents van het gegeven id 1 dan wel 0 teruggeeft.

Omdat het hier om een subquery gaat ... valt er niet echt iets te indexeren. Is er een andere manier om dat toch voor elkaar te krijgen? Deze oplossing heb ik overigens gekozen, omdat ik de stored procedure niet in de SELECT clause kan neerzetten ... da mag nie.

Acties:
  • 0 Henk 'm!

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

MBV

* MBV neemt de houding van jouw icon aan :/.
Vziw wordt eerst SELECT(...) AS tmp gedaan, en daarna de WHERE. Dat hij niet meer gaat optimaliseren als jij een stored procedure gebruikt om te filteren snap ik ook wel, daar moet je zoveel verbanden voor leggen dat dat niet meer werkt.

Volgens mij gebruik je je stored procedures niet op een erg handige manier, als ik het zo zie.

Acties:
  • 0 Henk 'm!

  • gvanh
  • Registratie: April 2003
  • Laatst online: 02-12-2023

gvanh

Webdeveloper

Topicstarter
Volgens mij gebruik je je stored procedures niet op een erg handige manier, als ik het zo zie.
Ben bang dat ik je daarin gelijk moet geven ... alleen weet ik niet hoe het anders zou moeten.

De hasPermission() stored procedure gaat omhoog kijken in de boomstructuur of er rechten ge-inherit zijn van parents. Dat doet hij eerst op het niveau van de gebruiker (die rechten gaan voor de rechten van de gebruikersgroepen (rollen) van de gebruiker) ... als die niet specifiek ingesteld zijn, dan wordt er hetzelfde gedaan voor de rollen. Ik ben al een lange tijd (echt een lange tijd) bezig met het herschrijven van de basis-query die dit kan. Tot nu toe heb ik nog niets gevonden dat sneller is dan deze oplossing.

Acties:
  • 0 Henk 'm!

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

MBV

Waarom doe je het niet precies andersom: maak een view of stored procedure die de rechten per gebruiker ophaalt. Die kan MySQL cachen, of je zou dat zelf in een tabel kunnen cachen. Daar join je dat stuk /*algemene query op 2 tabellen */ mee, zodat MySQL allerlei optimalisaties kan doen.
Wat jij beschrijft kan namelijk nogal uit de hand lopen qua doorlooptijd, en MySQL zal het een stuk minder druk krijgen als je dat stuk weghaalt.

En schakel dan ook meteen over naar InnoDB: dan kan je triggers zetten op wijzigingen in de rechtentabellen, zodat je het vlaggetje "Moet-geupdate-worden" in je cache-tabel op TRUE komt te staan, en hij het opnieuw berekent :)

[ Voor 20% gewijzigd door MBV op 10-10-2007 00:09 ]


Acties:
  • 0 Henk 'm!

  • gvanh
  • Registratie: April 2003
  • Laatst online: 02-12-2023

gvanh

Webdeveloper

Topicstarter
Ik heb je post 5x gelezen. Maar snap volgens mij nog niet helemaal wat je bedoelt.

Je zegt
waarom doe je het niet precies andersom, maak een view of stored procedure die de rechten per gebruiker ophaalt
Maar ik haal nu met mijn stored-procedure al de rechten per gebruiker per object op.

Wanneer ik een tabel zou maken met alle rechten van alle gebruikers op alle objecten dan krijg je (wat ik zo snel kan verzinnen) het volgende rekensommetje:

<aantal objecten> x <aantal mogelijke rechten (lezen, schrijven, etc.)> x <aantal gebruikers> x <aantal rollen/gebruikersgroepen per gebruiker>

100.000 x 10 x 100 x 3 = 3 x 10^8

En die tabel zou dan bij iedere wijziging van de objecten-tabel geüpdate moeten worden.
Correct me if i'm wrong ... maar dat lijkt geen ideale oplossing.

Acties:
  • 0 Henk 'm!

  • FragFrog
  • Registratie: September 2001
  • Laatst online: 22:47
LauPro schreef op dinsdag 09 oktober 2007 @ 16:41:
Dit is absoluut onzin. Je kan beter de gegenereerde output cachen in plain HTML files die je elke 5 minuten ververst.
Met stom ^^.

Natuurlijk heb je dynamische delen op je site staan, maar van 1 of 2 queries wordt een site niet traag. Een forum bijvoorbeeld hoeft echt niet 50x per seconde het aantal posts in een sectie op te vragen, of elke minuut te controleren welke user moderator ervoor is.

Smarty bijvoorbeeld kan prima bepaalde delen van je site cachen, 't is even een gepuzzel om te zoeken welke delen dat moeten zijn en hoe lang je elk deel wilt cachen, maar als je't eenmaal aan de praat hebt werkt't wel prima :Y)

En queries die 10 seconden duren als er 50 man tegelop op je server zit lijkt mij ook goed mis gaan, maar dat is een ander verhaal :+

[ Voor 8% gewijzigd door FragFrog op 10-10-2007 22:42 ]

[ Site ] [ twitch ] [ jijbuis ]


Acties:
  • 0 Henk 'm!

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

MBV

gvanh schreef op woensdag 10 oktober 2007 @ 17:50:
Ik heb je post 5x gelezen. Maar snap volgens mij nog niet helemaal wat je bedoelt.

Je zegt
[...]


Maar ik haal nu met mijn stored-procedure al de rechten per gebruiker per object op.

Wanneer ik een tabel zou maken met alle rechten van alle gebruikers op alle objecten dan krijg je (wat ik zo snel kan verzinnen) het volgende rekensommetje:

<aantal objecten> x <aantal mogelijke rechten (lezen, schrijven, etc.)> x <aantal gebruikers> x <aantal rollen/gebruikersgroepen per gebruiker>

100.000 x 10 x 100 x 3 = 3 x 10^8

En die tabel zou dan bij iedere wijziging van de objecten-tabel geüpdate moeten worden.
Correct me if i'm wrong ... maar dat lijkt geen ideale oplossing.
Dat is idd precies wat ik bedoel, en afhankelijk van de schaalgrootte en de huidige verdeling van je rechten over tabellen misschien sneller. Als jij roept dat er 100.000 items zijn, dan roep ik dat er 100 van die items het meest gebruikt zijn, en dat je daarmee een aantal queries fors zou kunnen versnellen. Maar helaas worden je queries wel een stuk complexer van op twee plekken je gegevens bijhouden ;)

Ik denk dus dat je het beste kan beginnen met je HTML cachen. Of, wat misschien ook toepasbaar is (zo gebeurt dat bij mij op mijn werk) je doet de rechten-check op PHP-niveau, en cached dat in een session (of waar je de gebruikersnaam nu al opslaat, als dat geen session maar iets 'veiligers' is)
FragFrog schreef op woensdag 10 oktober 2007 @ 22:41:
[...]

Met stom ^^.

Natuurlijk heb je dynamische delen op je site staan, maar van 1 of 2 queries wordt een site niet traag. Een forum bijvoorbeeld hoeft echt niet 50x per seconde het aantal posts in een sectie op te vragen, of elke minuut te controleren welke user moderator ervoor is.

Smarty bijvoorbeeld kan prima bepaalde delen van je site cachen, 't is even een gepuzzel om te zoeken welke delen dat moeten zijn en hoe lang je elk deel wilt cachen, maar als je't eenmaal aan de praat hebt werkt't wel prima :Y)

En queries die 10 seconden duren als er 50 man tegelop op je server zit lijkt mij ook goed mis gaan, maar dat is een ander verhaal :+
Paradigit.nl heeft queries die nog wel langer duren :X Nee, ik ga je niet vertellen met welke pagina die te maken hebben, en ja, er wordt aan caching gedaan :+.

Acties:
  • 0 Henk 'm!

  • gvanh
  • Registratie: April 2003
  • Laatst online: 02-12-2023

gvanh

Webdeveloper

Topicstarter
Dank voor alle reacties. Uiteraard zijn er veel niveau's waarop dingen beter kunnen. Momenteel ben ik toch aan het focussen op het optimaliseren van de normale queries. Zo heb ik al veel (een factor 100) gewonnen op een subquery door de sortering te doen op velden uit één van de twee tabellen die worden gejoined. Hiervoor heb ik wel enige redundancy, maar het scheelt dus veel in snelheid.

Waar ik nu mee bezig ben is het volgende:

MySQL:
1
SELECT tmp.* FROM ( <SELECT SUBQUERY> ) AS tmp


In bovenstaande query wordt de subquery in 0,002 seconde uitgevoerd (lijkt me prima) ... maar de totale query in 0,2 seconde. Dat scheelt dus nogal!

Ik wil het nu zo aan het aanpassen, dat ik een TEMP table maak van de subquery, om daar vervolgens mee verder te gaan. Ben even benieuwd in hoeverre dat scheelt. Eerste tests doen vermoeden dat het wel wat scheelt.

UPDATE:
Dat is spijtig. Het maken van een TEMP table duurt precies even lang als het uitvoeren van de query zoals hij hierboven staat. Blijkbaar maakt MySQL zelf intern ook al gebruik van het opzetten van een temporary table.

[ Voor 11% gewijzigd door gvanh op 11-10-2007 11:17 ]


Acties:
  • 0 Henk 'm!

  • FragFrog
  • Registratie: September 2001
  • Laatst online: 22:47
MBV schreef op donderdag 11 oktober 2007 @ 09:38:
Paradigit.nl heeft queries die nog wel langer duren :X Nee, ik ga je niet vertellen met welke pagina die te maken hebben, en ja, er wordt aan caching gedaan :+.
Als jij een voor consumenten beschikbare pagina hebt die alleen aan queries al meer dan 10 seconden nodig heeft om opgebouwd te worden blijf ik bij mijn standpunt dat je dan iets niet goed doet hoor ;)

Evengoed, als je een admin tool hebt om tables te controleren en bij te werken (wat je bij vBulletin bijvoorbeeld hebt) maakt het ook weer niet uit als je een keer een paar minuten moet wachten. Iets met context :+

* FragFrog heeft zo bijvoorbeeld nog eens een poortscan webapp omgeschreven naar httpXMLrequests voor elke poort zodat de client netjes zelf de requests na elkaar naar de server verstuurde, pagina staat er direct alleen voordat alle data er is ben je soms een paar minuten verder :Y)

[ Site ] [ twitch ] [ jijbuis ]


Acties:
  • 0 Henk 'm!

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

MBV

tja, dat wordt dan ook beschouwd als legacy ;) en ik doe alleen wat onderhoud en tweak-achtige dingen. Laatst kwam ik nog iets leuks tegen: opzoeken van een productplaatje duurde meerdere seconden. Werd leuk toen iemand meerdere plaatjes op 1 pagina wilde hebben :X

Zodra ik weer tijd heb ga ik een slow query log laten maken en zorgen dat die queries sneller worden. Dat zal wel niet meer lukken voor de nieuwe site er is, ben ik bang :/

Acties:
  • 0 Henk 'm!

  • gvanh
  • Registratie: April 2003
  • Laatst online: 02-12-2023

gvanh

Webdeveloper

Topicstarter
Optimalisatie heeft bij mij nu toch wel redelijk succes gehad. Bij de meeste pagina's/websites worden nu alle queries uitgevoerd in < 0.05 seconden. Dat lijkt me prima. Alleen bij tellen gaat het nu nog mis, omdat ALLE rows dan op rechten moeten worden gecontroleerd.

Ben nu bezig met het opzetten van een "educated guess" waarbij 500 willekeurige rows uit de database worden gehaald en worden geteld met rechten-restricties en zonder rechten-restricties. Het percentage met t.o.v. zonder is dan een indicatie voor het totaal. Dat lijkt voorlopig redelijk te werken.

[ Voor 6% gewijzigd door gvanh op 12-10-2007 09:10 ]

Pagina: 1