sql >> Database teknologi >  >> RDS >> Mysql

Sådan optimerer du forespørgsler i en database - det grundlæggende

Du er nødt til at kigge op for alle steder og for hver join...på betingelse. De to fungerer på samme måde.

Antag, at vi skriver

select name
from customer
where customerid=37;

På en eller anden måde skal DBMS finde posten eller posterne med kundeid=37. Hvis der ikke er noget indeks, er den eneste måde at gøre dette på at læse hver post i tabellen, der sammenligner kunde-id'et med 37. Selv når den finder en, kan den ikke vide, at der kun er én, så den skal blive ved med at lede efter andre.

Hvis du opretter et indeks på kunde-id, har DBMS måder at søge i indekset meget hurtigt. Det er ikke en sekventiel søgning, men, afhængigt af databasen, en binær søgning eller en anden effektiv metode. Præcis hvordan er ligegyldigt, accepter, at det er meget hurtigere end sekventielt. Indekset fører det derefter direkte til den eller de relevante poster. Ydermere, hvis du angiver, at indekset er "unik", så ved databasen, at der kun kan være et, så det spilder ikke tid på at lede efter et sekund. (Og DBMS forhindrer dig i at tilføje et sekund.)

Overvej nu denne forespørgsel:

select name
from customer
where city='Albany' and state='NY';

Nu har vi to betingelser. Hvis du kun har et indeks på et af disse felter, vil DBMS bruge det indeks til at finde en delmængde af posterne og derefter søge efter dem. For eksempel, hvis du har et indeks på staten, vil DBMS hurtigt finde den første post for NY, derefter søge sekventielt på udkig efter city='Albany' og stoppe med at lede, når den når den sidste post for NY.

Hvis du har et indeks, der inkluderer begge felter, dvs. "opret indeks på kunde (stat, by)", så kan DBMS straks zoome til de rigtige poster.

Hvis du har to separate indekser, et på hvert felt, vil DBMS have forskellige regler, som det gælder for at bestemme, hvilket indeks der skal bruges. Igen, præcis hvordan dette gøres afhænger af det bestemte DBMS du bruger, men grundlæggende forsøger det at føre statistik over det samlede antal poster, antallet af forskellige værdier og fordelingen af ​​værdier. Derefter vil den søge i disse poster sekventielt efter dem, der opfylder den anden betingelse. I dette tilfælde vil DBMS sandsynligvis observere, at der er mange flere byer, end der er stater, så ved at bruge byindekset kan det hurtigt zoome til 'Albany'-posterne. Derefter vil den sekventielt søge i disse, og kontrollere tilstanden for hver mod 'NY'. Hvis du har optegnelser for Albany, Californien, vil disse blive sprunget over.

Hver joinforbindelse kræver en form for opslag.

Sig, at vi skriver

select customer.name
from transaction
join customer on transaction.customerid=customer.customerid
where transaction.transactiondate='2010-07-04' and customer.type='Q';

Nu skal DBMS beslutte, hvilken tabel der skal læses først, vælge de relevante poster derfra og derefter finde de matchende poster i den anden tabel.

Hvis du havde et indeks på transaction.transactiondate og customer.customerid, ville den bedste plan sandsynligvis være at finde alle transaktionerne med denne dato, og derefter for hver af disse finde kunden med det matchende kunde-id og derefter kontrollere, at kunden har den rigtige type.

Hvis du ikke har et indeks på customer.customerid, så kunne DBMS hurtigt finde transaktionen, men så skulle den for hver transaktion sekventielt søge i kundetabellen på udkig efter et matchende kunde-id. (Dette ville sandsynligvis være meget langsomt.)

Antag i stedet, at de eneste indekser, du har, er på transaction.customerid og customer.type. Så ville DBMS sandsynligvis bruge en helt anden plan. Det ville sandsynligvis scanne kundetabellen for alle kunder med den korrekte type, derefter for hver af disse finde alle transaktioner for denne kunde og sekventielt søge efter den rigtige dato.

Den vigtigste nøgle til optimering er at finde ud af, hvilke indekser der virkelig vil hjælpe og oprette disse indekser. Ekstra, ubrugte indekser er en byrde for databasen, fordi det kræver arbejde at vedligeholde dem, og hvis de aldrig bliver brugt, er det spild indsats.

Du kan fortælle, hvilke indekser DBMS'et vil bruge til en given forespørgsel med EXPLAIN-kommandoen. Jeg bruger dette hele tiden til at afgøre, om mine forespørgsler bliver optimeret godt, eller om jeg skal oprette yderligere indekser. (Læs dokumentationen om denne kommando for en forklaring af dens output.)

Advarsel:Husk, at jeg sagde, at DBMS fører statistik over antallet af poster og antallet af forskellige værdier og så videre i hver tabel. EXPLAIN kan give dig en helt anden plan i dag, end den gav i går, hvis dataene er ændret. For eksempel, hvis du har en forespørgsel, der forbinder to tabeller, og den ene af disse tabeller er meget lille, mens den anden er stor, vil den være forudindtaget mod at læse den lille tabel først og derefter finde matchende poster i den store tabel. Tilføjelse af poster til en tabel kan ændre, hvad der er større, og dermed få DBMS til at ændre sin plan. Derfor bør du forsøge at lave EXPLAINS mod en database med realistiske data. At køre mod en testdatabase med 5 poster i hver tabel er af langt mindre værdi end at køre mod en live database.

Der er meget mere, der kunne siges, men jeg vil ikke skrive en bog her.



  1. Får MYSQL-fejl:Fejlkode:2006 - MySQL-serveren er gået væk

  2. MySQL-søgeforespørgsel på to forskellige felter

  3. Hvad er de levedygtige databaseabstraktionslag for Python

  4. Sådan fungerer INSERT()-funktionen i MariaDB