Permalänk
Medlem

Index i databasen

Hej, jag heter Meat och jag är en n00b med långsam databas.

Jag begriper att allt har med felaktig indexering att göra men vet inte riktigt hur jag ska göra för att hitta boven. Finns det nåt sätt att mäta hur lång tid det tar att göra olika anrop? Gärna direkt i phpMyAdmin...

Allt funkade bra tills jag gjorde några krångliga frågor med mycket JOIN och nästlade SELECT-satser som är till för att man ska kunna se en lista på alla inlägg man inte har läst. Så det kan bero på själva frågorna också, men visst ska man kunna nästla utan för mycket prestandaförlust?

Hilfe

Permalänk
Medlem

För att se vilket anrop som tog tid brukar jag göra på följande sätt;

function sql_query($query) {
global $queries, $query_stat;
$queries++;
$mtime = microtime(); // Get Current Time
$mtime = explode (" ", $mtime); // Split Seconds and Microseconds
$mtime = $mtime[1] + $mtime[0]; // Create a single value for start time
$query_start_time = $mtime; // Start time
$result = mysql_query($query);
$mtime = microtime();
$mtime = explode (" ", $mtime);
$mtime = $mtime[1] + $mtime[0];
$query_end_time = $mtime; // End time
$query_time = ($query_end_time - $query_start_time);
$query_time = substr($query_time, 0, 8);
$query_stat[] = array("seconds" => $query_time, "query" => $query);
return $result;
}

Då kan du använda funktionen sql_query istället för mysql_query så kommer den även mäta tiden det tog att utföra anropet, och för att sedan visa alla anrop och tidsangivelser:
foreach ($query_stat as $key => $value) {
print("[".($key+1)."] => <b>".($value["seconds"] > 0.01 ? "<font color=\"red\" title=\"I suggest you should optimize this query.\">".$value["seconds"]."</font>" : "<font color=\"green\" title=\"This query doesn't need's optimization.\">".$value["seconds"]."</font>" )."</b> [$value[query]]<br />\n");
}

Permalänk
Medlem

Eller så kör du frågan direkt i phpmyadmin. där står hur lång tid frågan kör.. kör även en EXPLAIN EXTENDED på den så får du reda på hur dålig/bra den är: http://dev.mysql.com/doc/refman/5.0/en/explain.html

Permalänk
Medlem

Tack för svaren! Jag började med EXPLAIN (verkade enklast) och har indexerat om lite samt formulerat om en del av frågan. Tror det blev bättre. Nu har fältet "rows" i EXPLAIN-outputen inga värden som är högre än 25. Tyvärr säger alla rader fortfarande "using where", "using filesort", "using index" osv.

Verkar som att problemet är att jag använder samma tabell i databasen i olika frågor och plockar ut olika saker från den. Ena gången skulle det passa att ha index på en kolumn och andra gången borde indexet vara ett annat. Nu har jag provat med ett index som innehåller båda kolumnerna men det förbättrar bara lite och är förmodligen inte kosher.

Vilket är nästa steg? Please, försök tänka på min inkompetens som rörande och ge mig några fingervisningar

Permalänk
Medlem

using index är bra Det är fulltablescan som tar mest tid.

Du får nog tala om hur tabellen ser ut, hur stor den är, samt några exempel på frågor om vi ska kunna hjälpa mer.

Permalänk
Medlem

Det är ett litet forum som jag har gjort själv, med tabeller för trådar, poster och besök samt en för medlemmar men den är inte viktig för exemplet.

TRÅDAR har fälten
trådnr (primärnyckel)
rumsnr (index)
medlemsnr
rubrik
datum
status
Liten tabell, under 50 rader.
(rumsnumret är för att det finns olika avdelningar i forumet, men inte så många så att jag har brytt mig om att göra en tabell av det)

POSTER har fälten
postid (primärnyckel)
rumsnr
trådnr (index tillsammans med datum)
medlemsnr
datum (index tillsammans med trådnr)
text
Ett tusental rader.

BESÖK sparar
trådnr (unik nyckel tillsammans med medlemsnr)
medlemsnr (unik nyckel tillsammans med trådnr)
datum (index)
Ett par hundra rader kanske, det blir inte mer än medlemsantalet*trådantalet men allt är ju i extremt liten skala.

En fråga som tar lång tid är den här, som körs när man är i ett rum. Den tar fram alla trådar som hör till rummet och sorterar på status och datum, dessutom tar den fram senaste gången medlemmen var i tråden och datum för senaste post så att det går att visa om det finns olästa inlägg.

SELECT t.rubrik, t.status, t.trådnr, b.datum AS senaste, p.datum FROM (trådar AS t LEFT JOIN besök AS b ON t.trådnr = b.trådnr AND b.medlemsnr = $id) JOIN poster AS p ON p.trådnr=t.trådnr WHERE t.rumsnr=$rumsnr AND p.datum IN (SELECT MAX( p.datum ) FROM poster AS p JOIN trådar AS t ON p.trådnr = t.trådnr WHERE t.rumsnr = $rumsnr GROUP BY p.trådnr) ORDER BY t.status, p.datum DESC

Det finns ett annat segt ställe men den är nästan lika så löser jag ovanstående bör den andra också vara biff. Problemet verkar vara den nästlade SELECT-satsen som ska hitta maxdatumet för alla trådar. Men jag inser ju att jag JOINar väldigt mycket också. Och att webbhotellet inte är det snabbaste.

En annan sak som förbryllar mig är att när jag kollar tidsåtgången för frågan så är den 2-3 sekunder, men kollar jag den direkt igen är den nere på under en sekund. Men phpMyAdmin kanske kommer ihåg resultatet bara?

Permalänk
Medlem
Skrivet av Meat:

En annan sak som förbryllar mig är att när jag kollar tidsåtgången för frågan så är den 2-3 sekunder, men kollar jag den direkt igen är den nere på under en sekund. Men phpMyAdmin kanske kommer ihåg resultatet bara?

Det är att hämta datablock från disk som tar tid, när du hämtar andra gången så ligger de redan i minnet.
Antalet jämförelser kan du dock sänka genom att lägga till ett bra index.
Ju fler index man har desto längre tid kommer inserts ta.

Visa signatur

I'm Winston Wolfe. I solve problems.

Permalänk
Medlem
Skrivet av matti4s:

Det är att hämta datablock från disk som tar tid, när du hämtar andra gången så ligger de redan i minnet.
Antalet jämförelser kan du dock sänka genom att lägga till ett bra index.
Ju fler index man har desto längre tid kommer inserts ta.

Som jag var inne på då :-).

Jo, det är ju det här med bra index som är svårt. Som jag förstår det kan jag inte lägga två index på samma tabell och tro att mysql kommer använda båda.

Permalänk
Medlem
Skrivet av Meat:

Som jag var inne på då :-).

Jo, det är ju det här med bra index som är svårt. Som jag förstår det kan jag inte lägga två index på samma tabell och tro att mysql kommer använda båda.

Jo har du flera kommer MySQL välja det index som är bäst för just den query du kör.

Visa signatur

I'm Winston Wolfe. I solve problems.

Permalänk
Medlem

Då har jag gjort fel på annat sätt för frågan ovan går riktigt långsamt om jag indexerar poster.trådnr och poster.datum var för sig.

Permalänk
Medlem
Skrivet av Meat:

Som jag var inne på då :-).

Jo, det är ju det här med bra index som är svårt. Som jag förstår det kan jag inte lägga två index på samma tabell och tro att mysql kommer använda båda.

Jodå, MySQL är smart. Man kan dessutom lägga flera kolumner i samma index, eller bara indexera X antal tecken i en kolumn (för långa index sägs ta längre tid).

Permalänk
Medlem
Skrivet av Ivarska:

Jodå, MySQL är smart. Man kan dessutom lägga flera kolumner i samma index, eller bara indexera X antal tecken i en kolumn (för långa index sägs ta längre tid).

Vad gör jag för fel då? Indexerade trådnr och datum var för sig nu, EXPLAIN säger using filesort =(