Se Hvordan MySQL bruger indekser .
Kontroller også, om MySQL stadig udfører en fuld tabelscanning efter at du har tilføjet yderligere 2000 rækker eller deromkring til dine user_metrics
bord. I små tabeller er access-by-index faktisk dyrere (I/O-mæssigt) end en tabelscanning, og MySQL's optimizer tager muligvis højde for dette.
I modsætning til mit tidligere indlæg , viser det sig, at MySQL også bruger en omkostningsbaseret optimering
, hvilket er meget gode nyheder - det vil sige, forudsat at du kører din ANALYZE
mindst én gang, når du mener, at mængden af data i din database er repræsentativ af fremtidig daglig brug.
Når du beskæftiger dig med omkostningsbaserede optimeringsværktøjer (Oracle, Postgres osv.), skal du sørge for periodisk at køre ANALYZE
på dine forskellige borde, efterhånden som deres størrelse stiger med mere end 10-15%. (Postgres vil som standard gøre dette automatisk for dig, mens andre RDBMS'er vil overlade dette ansvar til en DBA, dvs. dig.) Gennem statistisk analyse, ANALYZE
vil hjælpe optimizeren med at få et bedre indtryk af, hvor meget I/O (og andre tilhørende ressourcer, såsom CPU, der er nødvendige f.eks. til sortering) vil være involveret, når der skal vælges mellem forskellige kandidatudførelsesplaner. Kunne ikke køre ANALYZE
kan resultere i meget dårlige, nogle gange katastrofale planlægningsbeslutninger (f.eks. tager forespørgsler i millisekunder, nogle gange timer på grund af dårlige indlejrede loops på JOIN
s.)
Hvis ydeevnen stadig er utilfredsstillende efter at have kørt ANALYZE
, så vil du typisk kunne omgå problemet ved at bruge hints, f.eks. FORCE INDEX
, hvorimod du i andre tilfælde måske er faldet over en MySQL-fejl (f.eks. denne ældre , som kunne have bidt dig, hvis du brugte Rails' nested_set
).
Nu, da du er i en Rails-app , vil det være besværligt (og besejre formålet med ActiveRecord
) for at sende dine tilpassede forespørgsler med tip i stedet for at fortsætte med at bruge ActiveRecord
-genererede.
Jeg havde nævnt det i vores Rails-applikation alle SELECT
forespørgsler faldt til under 100 ms efter skift til Postgres, mens nogle af de komplekse joinforbindelser genereret af ActiveRecord
ville lejlighedsvis tage så meget som 15s eller mere med MySQL 5.1 på grund af indlejrede loops med indre tabelscanninger, selv når indekser var tilgængelige. Ingen optimizer er perfekt, og du bør være opmærksom på mulighederne. Andre potentielle ydeevneproblemer, som du skal være opmærksom på, udover optimering af forespørgselsplaner, er låsning. Dette er dog uden for rammerne af dit problem.