14. maj 2003 - 12:56Der er
17 kommentarer og 2 løsninger
Hvordan med index i tabeller?
Jeg kunne godt tænke mig at vide hvornår man bør oprette index's i sine tabeller, samt hvordan de skal oprettes, hvilke felter man kan oprette dem på og hvorfor? Gerne et rimeligt fyldestgørende, men let tilgængeligt svar...tak :-)
Selv udnytter jeg MySQL feature med at logge langsomme queries, og optimerer de bruger forespørgsler der tager 1 sekund eller mere.
Du skal lave index på de felter som dine tunge forespørgsler søger på, sortererer på, samt af og til de felter der selectes (for at modvirke en table scan).
For en given query kan du sætte EXPLAIN foran, hvilket vil få MySQL til at fortælle dig hvilke index den har tænkt sig at benytte, så du kan tilpasse dine index så den vælger dem (og undgår table scans).
Kig på www.mysql.com/doc for dokumentation af syntaks til oprettelse af index, eller benyt phpMyAdmin eller lign. værktøj til at administrere dine databaser med :)
Et lille eksempel som kan give dig et indblik i hvor meget hurtigere det vil gå hvis du indeksere rigtigt;
Et eksempel kunne være, en database med tabellen "test". Heri er der 1.000.000 rækker som har et id og et datetime felt. Lad os sige der er 11 ud af dissse 1.000.000 poster som er ældre end 2 timer og dem vil vi trække ud. Dette vil tage ca. 0.260246992111 Går vi nu ind og indeksere datetime (som vi jo søger på) i tabellen, og prøver igen, ja så får du en tid der siger: ca. 0.00083601474762 Altså er hastigheden steget ca. 300 gange.
Dit id felt vil typisk være en primær nøgle, og det er automatisk et unikt index samtidigt.
Man laver sjældent ét indeks på samtlige felter, da rækkefølgende af de enkelte felter i indekset er afgørende for om MySQL kan benytte det indeks i den enkelte query.
De felter der indgår i dit WHERE statement med = vil typisk være gode felter at have først i et index, og hvis du har et felt du søger på med > eller < vil det ofte med fordel kunne placeres sidst i indekset. Det er dog svært at sige noget generelt da det afhænger af det enkelte query.
Mit bedste bud er at benytte SLOW_QUERIES og optimere faktiske problemer istedet for at gætte sig frem til evt. flaskehalse.
Dog er det (næsten) altid en god ide at have indeks på fremmednøgle (som er primærnøgler i tabeller du joiner med)
Hvis man har uanede mængder at plad på sin server, og det samtidig er et stort svin af en server, så kan man godt indexere alle sine felter, men man skal huske på at for hvert index man putter på en tabel, så skal serveren opdatere index når der bliver slettet eller indsæt records, og derfor vil et index sløve sletninger og indsætninger/updates gevaldigt meget.
Man skal stort set kun oprette idex på felter som brugt i select statements i følgende:
Where xxx='yyy' (lav index på xxx) Order by ppp (lav index på ppp) where xxx='yyy' and zzz='yyy' (lav index på xxx+zzz, dvs index tofields(xxx,zzz)
Jo hvis det findes et index som matcher de krav der er til en query, så bruger mySQL det, ellers vil den bruge de index som ellers matcher, dvs.
Hvis din select er:
"select * from tabel where x=y and z=y"
så vil mySQL bruge index som følger,
index twofields(x,z) index onefielda x, index onefieldb z
Hvis der ikke er nogen index overhovedet, så er det at det bliver langsomt, da den skal hente alle records i tabellen og matche dem med din selec statement.
Når du laver index med flere felter, så skal du også huske at oprette dem med felterne i den rækkefølge du bruger i din select statement.
Dvs hvis "select * from a where x=y and z=y"
Så skal indexet være index twofields(x,z), ikke index twofields(z,y)
Jeg er ikke sikker når du bruger to forskellige selects, men jeg tror at det er nok med dit index med alle tre felter, men prøv at læse lidt i dokumentationen på www.mysql.com, den er faktisk rigtig god :)
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.