02. marts 2005 - 09:40Der er
38 kommentarer og 1 løsning
Performance, konvertering af tinytext kontra/til int
Ja, det er faktisk flere spørgsmål i et, med de hænger meget tæt sammen. Så jeg giver 30 point pr. spørgsmål.
Og jeg kan ikke argumentere for valget af felttyper, da jeg ikke har udarbejdet db'en, kun overtaget den fortsatte udvikling.
1) Jeg har en query, som bl.a. summerer den sammen pris hver måned for alle tilbud. Problemet er at denne query, tager uforholdsmæssigt lang tid ca. 40s-60s og db'en bliver jo kun størrere. Jeg har så lagt index, på felterne i where-delen uden den helt store forbedring. Men via tests, både med og uden SUM-delen, kører det hurtigt nok, hvis den ikke er med. Derfor må jeg jo konkludere at problemet må skyldes summeringen. Feltet som indeholder det enkelte tilbuds samlede pris, er af typen tinytext. Jeg har så den teori, at lave en SUM(tinytext) tager vildt lang tid, i forhold til hvis feltet havde været af typen Int, altså SUM(INT). Men passer det?
2) Afhænger af svaret på punkt 1, men er INT meget hurtigere, så skal jeg jo måske have konvereteret feltet, problemet er så bare, at db'en jo indeholder arbejdsdata, som absolut ikke må blive slettet. Hvad vil der ske ved en konvertering, vil jeg miste data?
Jeg er ikke helt vild med at skulle konvertere via en midlertidig tabel, tror I data vil bliver ændret, hvis jeg bare f.eks. via phpmyadmin ændre typen.
Selvfølgelig skal jeg have taget backup, jeg ville sådan set også bare lige tjekke, og især gerne høre fra nogle som har foretaget en konvertering, faldgruber o.l.
Jeg vil helt klart mene at: - select med konvertering fra RIGTIG til MIDLERTIDIG - check MIDLERTIDIG - drop RIGTIG - select at fra MIDLERTIDIG TIL RIGTIG - drop RIGTIG er en low risk løsning
Jeg har lige prøvet at ændre typen på en test-db jeg har, og der gik det uden problemer. Test-db'en indeholder bare langt fra så mange data som drifts-db'en, men jeg vil så resten af dagen, holde øje med, om det har indflydelse på noget andet.
Jeg skal lave en test på driften i eftermiddag/aften, så der ved jeg sikkert mere, men på test-db'en har der ikke været problemer, selvom jeg bare ændrede datatypen via phpmyadmin, så det vil jeg også prøve på driften.
Men jeg skal nok vende tilbage, når jeg ved noget mere.
Uha, der er flere af dem, jeg lister dem lige op efterfølgende. En anden mærkelige ting, er også at den ikke returnere noget, andet end en query. Men på testdb'en kan den godt returnere en oversigt.
'$startdato' && r4 < '$slutdato' $where GROUP BY maaned ORDER BY maaned";
$res = mysql_query($sql) or die($sql); while ($row = mysql_fetch_row($res)) { $tilbud[$row[0]]['antal'] = $row[1]; $tilbud[$row[0]]['sum'] = $row[2]; }
// Finder de nødvendige data til tabellen // $sql = "SELECT month(oprettet) as maaned, count(*) as antal, sum(r504) as ordresum, sum(r477a) as staalpris, sum(r477) as
tonnage, sum(r503) as fortjeneste, avg(r502) as db, 'test' as budget, 'test' as budgetafv FROM ordre, ordre0, ordre4, ordre5
LEFT JOIN kunde ON kunde_hidden = kunde.id WHERE ordre.id = ordre0.tilbudsnummer && ordre0.tilbudsnummer =
ordre4.tilbudsnummer && ordre4.tilbudsnummer = ordre5.tilbudsnummer && oprettet >= '$startdato' && oprettet < '$slutdato'
$where GROUP BY maaned ORDER BY oprettet";
$sql = "SELECT month(r2) as maaned, count(*) as antal, sum(r504) as ordresum, sum(r477a) as staalpris, sum(r477) as tonnage,
avg(r509) as krkg, sum(r503) as fortjeneste, avg(r502) as db, 'test' as budget, 'test' as budgetafv FROM (SELECT ordre,
MAX(rev) as rev FROM ordre GROUP BY ordre) as o, ordre, ordre0, ordre4, ordre5 LEFT JOIN kunde ON kunde_hidden = kunde.id
$where"; $res = mysql_query($sql) or die($sql);; list($tilbud_antal, $tilbud_sum) = mysql_fetch_row($res); // Finder total værdierne // $sql = "SELECT 'Total', count(*) as antal, sum(r504) as ordresum, sum(r477a) as staalpris, sum(r477) as tonnage, avg(r509)
as krkg, sum(r503) as fortjeneste, avg(r502) as db, 'test' as budget, 'test' as budgetafv, 'test' as ordreprocent, 'test' as
omsprocent FROM ordre, ordre0, ordre4, ordre5 LEFT JOIN kunde ON kunde_hidden = kunde.id WHERE ordre.id =
Og der er index på følgende felter: ordre5/tilbud5.tilbudsnummer, ordre5.r504, ordre4/tilbud4.tilbudsnummer, tilbud3.tilbudsnummer, tilbud2.tilbudsnummer, tilbud1.tilbudsnummer, ordre0/tilbud0.tilbudsnummer, ordre0.r4, ordre.ordre og ordre.rev
Ja, det var en ordentlig omgang. Det virker nu ikke særligt tillidsvækkende at den ikke returnerer det samme på de 2 maskiner. Det var måske værd at sætte: error_reporting(E_ALL); for at afsløre evt. fejl. Men det må være et must at indkredse synderen, altså den tidskrævende forespørgsel, evt. ved at teste en ad gangen.
Nu kan jeg ikke med 100% sikkerhed huske hvilke det er, men det drejer sig om 2. Jeg kan i hvert fald huske, at jeg testede af en query, både med og uden sum(r504), og uden kørte den hurtigst nok, men med GAAAAB hvor langsomt. Hvilket også var grunden til at jeg undersøgte db'en, og så slog det mig, at int burde være hurtigere at beregne på end tinytext.
Den der error_reporting(E_ALL) skal den i stedet for die eller hva?
Jeg glemte at sige, at så vidt jeg ved køre databasen på en terminal-server, og selvfølgelig har det noget at sige, men hvor meget i forhold til en dedikeret database-server?
Okay, jeg har nu fundet ud af at error_reporting skal sættes i php.ini, men det er den godt nok flere gang, men jeg er heller ikke så vild, for at skulle ændre i den.
Okay de 2 querys som trækker tænder ud af systemet:
1) SELECT month(r2) as maaned, count(*) as antal, sum(r504) as `sum` FROM (SELECT tilbud, MAX(rev) as rev FROM tilbud GROUP BY tilbud) as t, tilbud, tilbud0, tilbud5 LEFT JOIN kunde ON kunde_hidden = kunde.id WHERE t.tilbud = tilbud.tilbud && t.rev = tilbud.rev && tilbud.id = tilbud0.tilbudsnummer && tilbud0.tilbudsnummer = tilbud5.tilbudsnummer && r4 >= '$startdato' && r4 < '$slutdato' $where GROUP BY maaned ORDER BY maaned
2) SELECT count(*) as antal, sum(r504) as `sum` FROM (SELECT tilbud, MAX(rev) as rev FROM tilbud GROUP BY tilbud) as t, tilbud, tilbud0, tilbud5 LEFT JOIN kunde ON kunde_hidden = kunde.id WHERE t.tilbud = tilbud.tilbud && t.rev = tilbud.rev && tilbud.id = tilbud0.tilbudsnummer && tilbud0.tilbudsnummer = tilbud5.tilbudsnummer && r4 >= '$startdato' && r4 < '$slutdato' $where
Begge 2 er dog hurtige nok (ca. 1 sek.), hvis jeg fjerner sum(r504) as sum, hvilket også var grunden til, at jeg tænkte at en konvertering måske kunne gøre det.
Det er bare ment som et midlertidigt tiltag for at sikre dig at der ikke er fejl i selve scriptet, da du jo ikke for returneret det samme som fra din test-db.
Da du har felttypen INT og index på feltet, er jeg ikke sikker på hvad du så skal stille op. Der er nogle forskellige ting du kan prøve, bl.a. EXPLAIN syntax for at sikre dig at der er index på alle de rigtige felter. Og måske prøve med en sortering af dine index, det står beskrevet her: http://dev.mysql.com/doc/mysql/en/select-speed.html
Øh, error_reporting(E_ALL) gør ikke rigtigt noget, i hvert fald ikke i forhold til scriptet uden error. Man skal ikke sige echo ligger lignede til det, vel?
Jamen så er der hvertfald ikke noget galt med selve scriptet. Det var bare for at tjekke at der ikke var nogle småfejl, ift. at du ikke får de samme resulatater returneret som fra din testdb.
Kan det være fordi scriptet simpelthen tager for lang tid at eksekvere? Men så burde den vel komme med en fejlmeddelelse om at executiontime er udløbet?
Nej, den vil stoppe udførrelsen af scriptet og give dig en melding som du sagde med at executiontime er udløbet. Jeg kan altså ikke se hvad det er i den SUM() operation, der skulle gøre din forespørgsel SÅ langsom. Hvor store er dine tabeller? Har du prøvet at tjekke dine forespørgsler med EXPLAIN?
ja, hvis der er EXPLAIN via phpmyadmin du mener, men jeg fattede ikke så meget af, men jeg kan da godt ligge det op. Størrelsen på tabellerne kan jeg ikke lige huske, men jeg kan måske tjekke det på min egen maskine.
Explain giver dette resultat, og på min maskine tog det også ca 60 sek. at udføre queryen. id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY <derived2> ALL NULL NULL NULL NULL 1485 Using temporary; Using filesort 1 PRIMARY tilbud5 ALL tilbudsnummer NULL NULL NULL 1707 1 PRIMARY tilbud0 ref tilbudsnummer tilbudsnummer 4 test_kompetence.tilbud5.tilbudsnummer 1 Using where 1 PRIMARY tilbud eq_ref PRIMARY PRIMARY 3 test_kompetence.tilbud0.tilbudsnummer 1 Using where 1 PRIMARY kunde eq_ref PRIMARY,id PRIMARY 2 test_kompetence.tilbud0.kunde_hidden 1 Using index 2 DERIVED tilbud ALL NULL NULL NULL NULL 1707 Using temporary; Using filesort
Hov, nu har jeg sgu fundet den tror jeg nok. Jeg prøvede lige at sætte index på alt, hvad der var muligt at sætte index på, og så kørte den hurtigt nok. Testede mig så lidt frem til at det er Tilbud.tilbud, som er skyld i miseren.
Men vi må lige vente til på mandag, så jeg kan teste det på arbejde.
YES, det fik virkelig fjernet en sten fra mit bryst, det virke sgu, og håber det også bliver ved med det.
Nå men detox, du skal da have point, og du havde jo også ret i at det ikke var funktionen SUM(), som forudsagede den kritiske hastighed, selvom jeg troede det var den.
Ja, brugerne er også pludselig blevet helt vilde med, at køre statistiker over sig selv, så de bl.a. kan se hvor meget de har solgt for
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.