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

Hvordan fungerer MySQL-indekser?

Den første ting du skal vide er, at indekser er en måde at undgå at scanne hele tabellen for at opnå det resultat, du leder efter.

Der er forskellige slags indekser, og de er implementeret i lagringslaget, så der er ingen standard mellem dem, og de afhænger også af den lagringsmotor, du bruger.

InnoDB og B+Tree-indekset

For InnoDB er den mest almindelige indekstype det B+Tree-baserede indeks, der gemmer elementerne i en sorteret rækkefølge. Du behøver heller ikke få adgang til den rigtige tabel for at få de indekserede værdier, hvilket gør, at din forespørgsel vender tilbage meget hurtigere.

"Problemet" ved denne indekstype er, at du skal forespørge efter værdien længst til venstre for at bruge indekset. Så hvis dit indeks har to kolonner, sig efternavn og fornavn, er den rækkefølge, du forespørger på disse felter, betydende meget .

Så givet følgende tabel:

CREATE TABLE person (
    last_name VARCHAR(50) NOT NULL,
    first_name VARCHAR(50) NOT NULL,
    INDEX (last_name, first_name)
);

Denne forespørgsel ville drage fordel af indekset:

SELECT last_name, first_name FROM person
WHERE last_name = "John" AND first_name LIKE "J%"

Men den følgende ville ikke

SELECT last_name, first_name FROM person WHERE first_name = "Constantine"

Fordi du forespørger på first_name kolonne først, og det er ikke kolonnen længst til venstre i indekset.

Dette sidste eksempel er endnu værre:

SELECT last_name, first_name FROM person WHERE first_name LIKE "%Constantine"

For nu sammenligner du den del af feltet længst til højre i indekset.

Hash-indekset

Dette er en anden indekstype, som desværre kun hukommelsesbackend understøtter. Det er lynhurtigt, men kun nyttigt til fulde opslag, hvilket betyder, at du ikke kan bruge det til operationer som > , < eller LIKE .

Da det kun virker til hukommelsesbackend, vil du sandsynligvis ikke bruge det ret ofte. Den vigtigste sag, jeg kan komme i tanke om lige nu, er den, at du opretter en midlertidig tabel i hukommelsen med et sæt resultater fra en anden udvælgelse og udfører en masse andre valg i denne midlertidige tabel ved hjælp af hash-indekser.

Hvis du har en stor VARCHAR felt, kan du "emulere" brugen af ​​et hash-indeks, når du bruger et B-Tree, ved at oprette en anden kolonne og gemme en hash af den store værdi på den. Lad os sige, at du gemmer en url i et felt, og værdierne er ret store. Du kan også oprette et heltalsfelt kaldet url_hash og brug en hash-funktion som CRC32 eller en hvilken som helst anden hash-funktion til at hash url'en, når du indsætter den. Og så, når du skal forespørge efter denne værdi, kan du gøre noget som dette:

SELECT url FROM url_table WHERE url_hash=CRC32("http://gnu.org");

Problemet med ovenstående eksempel er, at siden CRC32 funktionen genererer en ganske lille hash, vil du ende med en masse kollisioner i de hash-værdier. Hvis du har brug for nøjagtige værdier, kan du løse dette problem ved at gøre følgende:

SELECT url FROM url_table 
WHERE url_hash=CRC32("http://gnu.org") AND url="http://gnu.org";

Det er stadig værd at hashe ting, selvom kollisionstallet er højt, fordi du kun udfører den anden sammenligning (strengen) med de gentagne hashes.

Desværre, ved at bruge denne teknik, er du stadig nødt til at ramme tabellen for at sammenligne url felt.

Afslut

Nogle fakta, som du kan overveje, hver gang du vil tale om optimering:

  1. Heltalssammenligning er langt hurtigere end strengsammenligning. Det kan illustreres med eksemplet om emulering af hash-indekset i InnoDB .

  2. Måske gør tilføjelse af yderligere trin i en proces den hurtigere, ikke langsommere. Det kan illustreres ved, at du kan optimere en SELECT ved at opdele den i to trin, så den første lagrer værdier i en nyoprettet tabel i hukommelsen, og kør derefter de tungere forespørgsler på denne anden tabel.

MySQL har også andre indekser, men jeg tror, ​​at B+Tree er det mest brugte nogensinde, og hash-en er en god ting at vide, men du kan finde de andre i MySQL-dokumentation .

Jeg anbefaler dig stærkt at læse "High Performance MySQL"-bogen, svaret ovenfor var bestemt baseret på kapitlet om indekser.



  1. TODATETIMEOFFSET() Eksempler i SQL Server

  2. Sådan returneres forespørgselsresultater som en kommasepareret liste i PostgreSQL

  3. Hvordan installeres en Python-pakke på Linux, så den findes af den allerede fungerende PostgreSQL 13 plpython3u-udvidelse?

  4. Sådan filtreres forespørgselsresultater i PostgreSQL