Query opsplitsen in tweeen

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Pagina: 1 2 volgende »

Pelckie

Pelckie

28/01/2008 14:28:00
Quote Anchor link
Hoi allemaal,

Ik heb een query die werkt, maar erg traaaag is.
Het lijkt me beter om hem in tweeen te splitsen, maar ik weet niet precies hoe...

Dit is de query:
mysql_query("SELECT YEAR(mct_sessions.date) AS Year, MONTH(mct_sessions.date) AS Month, COUNT(mct_paths.id) AS Pageviews, COUNT(DISTINCT mct_sessions.visitors_id) AS Visitors FROM mct_sessions INNER JOIN mct_paths ON mct_paths.session_id = mct_sessions.id WHERE mct_sessions.date BETWEEN date_format( str_to_date( '$startDates', '%e-%c-%Y' ) , '%Y-%m-%d' ) AND date_format( str_to_date( '$endDates', '%e-%c-%Y' ) , '%Y-%m-%d' ) GROUP BY Year, Month"

Het is een INNER JOIN van mct_paths en mct_sessions.
 
PHP hulp

PHP hulp

15/11/2024 12:57:41
 
Joren de Wit

Joren de Wit

28/01/2008 14:35:00
Quote Anchor link
De lengte van je query zal niet de oorzaak zijn dat hij traag is, dat zul je toch echt ergens anders moeten zoeken.

Hoe is het bijvoorbeeld gesteld met de normalisatie van je datamodel en hoeveel records praten we hier over. Heb je verder op een slimme manier indexen aangebracht op de kolommen in je tabel?

Dat laatste is voornamelijk in een tabel met veel records van groot belang. Gister nog kwam er iemand achter dat een query die eerst 40 seconde duurde, na het aanbrengen van indexen op de juiste kolommen nog maar 1 seconde duurde!
 
Frank -

Frank -

28/01/2008 14:40:00
Quote Anchor link
leesbaarheid wil ook nog wel eens helpen...
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
SELECT
  YEAR(mct_sessions.date) AS Year,
  MONTH(mct_sessions.date) AS Month,
  COUNT(mct_paths.id) AS Pageviews,
  COUNT(DISTINCT mct_sessions.visitors_id) AS Visitors
FROM
  mct_sessions INNER JOIN
    mct_paths ON mct_paths.session_id = mct_sessions.id
WHERE
  mct_sessions.date
    BETWEEN
      date_format( str_to_date( '$startDates', '%e-%c-%Y' ) , '%Y-%m-%d' )
    AND
      date_format( str_to_date( '$endDates', '%e-%c-%Y' ) , '%Y-%m-%d' )
GROUP BY
  Year, Month

Vervolgens ga je met EXPLAIN uitvogelen waaróm de query langzaam is. Lukraak de boel opknippen gaat je daar namelijk niet bij helpen.

De functies date_format() en str_to_date zullen in elk geval niet bijdragen aan het versnellen van het process, integendeel! Waarom geef je niet gewoon een correcte dataum op als input voor de query?
Gewijzigd op 01/01/1970 01:00:00 door Frank -
 
Pelckie

Pelckie

28/01/2008 14:44:00
Quote Anchor link
Bedankt voor de snelle reactie,

Ik heb volgens mij wel ver door genormaliseerd, ieerst was het minder ver door genormaliseerd en toen leek het juist sneller te gaan. Ik dacht misschien ligt het aan de JOINS die het traag maken.

Het gaat nu nog maar over circa 15000 records, maar dat zullen er alleen maar meer worden.

Dat indexeren dat heb ik nog niet geprobeerd, dus dat ga ik eens proberen.
 
Pelckie

Pelckie

28/01/2008 14:48:00
Quote Anchor link
pgFrank schreef op 28.01.2008 14:40:
De functies date_format() en str_to_date zullen in elk geval niet bijdragen aan het versnellen van het process, integendeel! Waarom geef je niet gewoon een correcte dataum op als input voor de query?


Ja, dat komt omdat de ingevoerde datum's gewoon op de 'europese' manier zijn ingevoerd. Ik kan het dan inderdaad beter met php eerst omzetten naar de goeie format...
 
Joren de Wit

Joren de Wit

28/01/2008 14:48:00
Quote Anchor link
Te ver normaliseren is mogelijk, maar zal zeker niet het eerste geval zijn dat problemen oplevert. Verder zijn 15.000 records helemaal niet veel maar het ontbreken van de juiste indexen zal in jouw geval de traagheid heel goed kunnen verklaren.

MySQL Indexes

Zie deze tutorial en ga met EXPLAIN aan de gang om uit te vogelen waarom jouw query traag is.
Gewijzigd op 01/01/1970 01:00:00 door Joren de Wit
 
Pelckie

Pelckie

28/01/2008 14:50:00
Quote Anchor link
Ok dat zal ik eens gaan doen,

bedankt voor de snelle en goede reacties..
 
Frank -

Frank -

28/01/2008 15:02:00
Quote Anchor link
Pelckie schreef op 28.01.2008 14:48:
pgFrank schreef op 28.01.2008 14:40:
De functies date_format() en str_to_date zullen in elk geval niet bijdragen aan het versnellen van het process, integendeel! Waarom geef je niet gewoon een correcte dataum op als input voor de query?


Ja, dat komt omdat de ingevoerde datum's gewoon op de 'europese' manier zijn ingevoerd. Ik kan het dan inderdaad beter met php eerst omzetten naar de goeie format...
ISO-formaat is ook Europees hoor.

Daarnaast zul je toch al in PHP moeten controleren of de datum wel een geldige datum is, MySQL zal dat meestal niet doen. Wanneer de datum correct is, zet hem in de juiste volgorde en slinger hem de query in. Scheelt weer performance aan de database-zijde.

ps. Welke versie van MySQL gebruik je? En welke MODE gebruik je?
 
Pelckie

Pelckie

29/01/2008 08:54:00
Quote Anchor link
mysql V4.1.20. @ MyISAM gebruiken ze hier, verouderd maarja. Kan dat ook snelheid schelen?
 
Jurgen assaasas

Jurgen assaasas

29/01/2008 09:38:00
Quote Anchor link
Leuk dat je dat gebruikt allemaal gebruikt maar met MyISAM kun je nooit relaties leggen tussen data, Zeg dat ze MySQL moeten updaten en InnoDB gebruiken of beter <pgFrank modus> een goede DB gebruiken zoals PgSQL</pgFrank modus>
Gewijzigd op 01/01/1970 01:00:00 door Jurgen assaasas
 
Joren de Wit

Joren de Wit

29/01/2008 09:59:00
Quote Anchor link
Zoals Jurgen al zegt: MySQL 4 kun je gewoon geen database noemen. Zeker met de MyISAM engine die jij nu gebruikt hangt alle data als een los hoopje zand aan elkaar en er hoeft maar iets te gebeuren of alles stort als een kaartenhuis ineen.

Met versie 5 van MySQL wordt het al beter, maar ook dan laat deze database nog genoeg te wensen over.

Ik weet niet bij welke host je zit, maar vraag dus eens hoe het zit met update van MySQL. Zijn ze niet van plan om hier in de zeer nabije toekomst verandering in te bregen, zou ik toch ten zeerste overwegen om over te stappen naar een andere host.

ps. Welke PHP versie draaien ze? Als dat op dit moment geen versie 5 is, heb je nog een reden om over te stappen ;-)
 
Pelckie

Pelckie

29/01/2008 10:27:00
Quote Anchor link
De situatie is niet bepaald ideaal hier, we zitten met php 4 en mysql 4 en myISAM. De rede dat ze niet willen updaten is omdat we met een aangepaste en je raadt het al een VEROUDERDE Joomla werken, dat zou dan teveel aanpassingen vereisen...

Ik ga in ieder geval mijn best doen om ze ervan te overtuigen dat het zo niet langer kan.

Is het trouwens omslachtig om een bestaand systeem om te bouwen van myISAM naar INNODB?
 
Joren de Wit

Joren de Wit

29/01/2008 10:41:00
Quote Anchor link
Pelckie schreef op 29.01.2008 10:27:
Ik ga in ieder geval mijn best doen om ze ervan te overtuigen dat het zo niet langer kan.
Bepaar je de moeite en zoek een andere host. Dat levert je veel meer op dan een stugge host van zijn fouten proberen te overtuigen. PHP 4 en MySQL 4, het is een schande!

Verhuizen van host zal je veel minder problemen geven ;-)

Om over te stappen op InnoDB zul je je tabellen opnieuw aan moeten maken. Als je echter al een goed datamodel hebt, hoef vervolgens alleen nog de onderlinge relaties tussen de tabellen aan te brengen dmv foreign keys. Tenslotte kun je de data gewoon kopieren vanuit de oude tabellen naar de nieuwe tabellen.

Het is dan alleen te hopen dat er nog geen conflicten zijn met de constraints die je aangebracht hebt. Is dat wel het geval, dan zal het waarschijnlijk het makkelijkste zijn om de tabellen weer helemaal opnieuw te vullen.
 
Frank -

Frank -

29/01/2008 11:24:00
Quote Anchor link
Als je toch gaat zoeken naar een betere provider, je valt je geen buil aan PostgreSQL... Kan alles wat MySQL kan, maar dan nog meer en nog sneller. Daarnaast is je data gegarandeerd veilig opgeslagen, dat is met MySQL (helaas) wel anders.
 
Pelckie

Pelckie

29/01/2008 17:13:00
Quote Anchor link
Ik heb jullie raad opgevolgd en het is nu al een stuk sneller, met namen het indexeren heeft veel geholpen.
De crux zit hem nu nog in een klein stukje code:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?php
while($Session = mysql_fetch_assoc($Query_All))//start while loop through paths
        {
            $end=0;
            $y=0;

            $Query_Session = MySQL_Query("SELECT page_id FROM mct_paths WHERE session_id ='".$Session['session_id']."' ");
            
            while($Page_ID = mysql_fetch_assoc($Query_Session)) //&& $End == 0) //start while in while
            {
                $y++;
                $Query_Pages = MySQL_Query("SELECT page_title FROM mct_hitpages WHERE id='".$Page_ID[page_id]."'");
                $Page = mysql_fetch_assoc($Query_Pages);
                $PageTotal = mysql_num_rows($Query_Session);
                
                $arrow = ($y == $PageTotal) ? "" : "<img src='images/arrow.png'>";
                
                if(strlen($List[$i])<350)
                {

                    $List[$i] .= $Page['page_title'].$arrow;//fill array
                }
                else
                {
                    if ($end==0)
                    {

                        $List[$i] .= "...";//fill array
                        $end=1;
                    }
                }
            }

            $i++;
        }

?>


Het moet nu telkens opnieuw een query uitvoeren, heeft iemand een idee hoe dit op een slimmere manier aan te pakken?
Gewijzigd op 01/01/1970 01:00:00 door Pelckie
 
Frank -

Frank -

29/01/2008 17:19:00
Quote Anchor link
leuk dit stukje PHP-code, maar het probleem zit hem (waarschijnlijk) in de indexen. Ga met EXPLAIN achterhalen hoe de database de query uitvoert en welke indexen worden gebruikt.

Binnen een while-lus een query uitvoeren is zelden een goed plan, dat kan een enorme berg queries opleveren.

Ps. $Page_ID[page_id] mag worden $Page_ID['page_id'] dus met quotes. page_id is geen constante maar een string. Hier had je ook een notice op horen te krijgen. Of heb je de error_reporting op een te laag niveau staan?
 
Joren de Wit

Joren de Wit

29/01/2008 17:21:00
Quote Anchor link
Als het daadwerkelijk 3 hele verschillende queries op 3 verschillende tabellen zou betreffen, kun je er waarschijnlijk niet omheen. Maar als ik zo eens kijk naar de queries die je gebruikt, krijg ik het sterke vermoeden dat je dit waarschijnlijk ook wel in 1 of 2 queries kunt oplossen...

Laat anders eens zien hoe je datamodel eruit ziet en omschrijf eens wat je precies uit die tabellen wilt ophalen. Dan kunnen we eens kijken :-)
 
Pelckie

Pelckie

29/01/2008 17:24:00
Quote Anchor link
pgFrank schreef op 29.01.2008 17:19:
Ps. $Page_ID[page_id] mag worden $Page_ID['page_id'] dus met quotes. page_id is geen constante maar een string. Hier had je ook een notice op horen te krijgen. Of heb je de error_reporting op een te laag niveau staan?


Bedankt, ik weet dat dit tussen quotes moet, was een typfout. Error report staat idd op een laag niveau, sterker nog het staat uit. Dus als ik bijvoorbeeld syntax errors heb dan is dat wel is lastig...
Gewijzigd op 01/01/1970 01:00:00 door Pelckie
 
Frank -

Frank -

29/01/2008 17:26:00
Quote Anchor link
EXPLAIN in MySQL.
 
Joren de Wit

Joren de Wit

29/01/2008 17:29:00
Quote Anchor link
Pelckie schreef op 29.01.2008 17:24:
Bedankt, ik weet dat dit tussen quotes moet, was een typfout.
Doe je ook wat met de anderen opmerkingen? Die zijn namelijk veel waardevoller...
 
Pelckie

Pelckie

29/01/2008 17:29:00
Quote Anchor link
Blanche schreef op 29.01.2008 17:21:
Laat anders eens zien hoe je datamodel eruit ziet en omschrijf eens wat je precies uit die tabellen wilt ophalen. Dan kunnen we eens kijken :-)


Sorry dat gaat me vandaag niet meer lukken. Ik zal morgen het datamodel even posten.

@ Blanche -> Ja daar doe ik zeker wat mee... niet zo snel... haha

Bedankt weer voor de snelle reacties!
Gewijzigd op 01/01/1970 01:00:00 door Pelckie
 

Pagina: 1 2 volgende »



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.