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

Hvordan fremskyndes antallet af udvalgte(*) med gruppe efter og hvor?

Her er flere ting, jeg ville prøve, i rækkefølge efter stigende sværhedsgrad:

(lettere) - Sørg for, at du har det rigtige dækkende indeks

CREATE INDEX ix_temp ON relations (relation_title, object_title);

Dette burde maksimere perf givet dit eksisterende skema, da (medmindre din version af mySQL's optimizer er virkelig dum!) det vil minimere mængden af ​​I/O'er, der er nødvendige for at tilfredsstille din forespørgsel (i modsætning til hvis indekset er i omvendt rækkefølge, hvor hele indekset skal scannes), og det vil dække forespørgslen, så du ikke behøver at røre ved det grupperede indeks.

(lidt sværere) - sørg for, at dine varchar-felter er så små som muligt

En af perf-udfordringerne med varchar-indekser på MySQL er, at når en forespørgsel behandles, vil den fulde deklarerede størrelse af feltet blive trukket ind i RAM. Så hvis du har en varchar(256), men kun bruger 4 tegn, betaler du stadig 256-byte RAM-forbruget, mens forespørgslen behandles. Av! Så hvis du nemt kan skrumpe dine varchar-grænser, burde dette fremskynde dine forespørgsler.

(sværere) - Normaliser

30 % af dine rækker med en enkelt strengværdi er et klart råb om normalisering til en anden tabel, så du ikke duplikerer strenge millioner af gange. Overvej at normalisere i tre tabeller og bruge heltals-id'er til at forbinde dem.

I nogle tilfælde kan du normalisere under dækslet og skjule normaliseringen med visninger, der matcher navnet på den aktuelle tabel... så behøver du kun at gøre dine INSERT/UPDATE/DELETE forespørgsler opmærksomme på normaliseringen, men kan lade dine SELECTs være i fred .

(sværeste) - Hash dine strengkolonner og indekser hasherne

Hvis normalisering betyder at ændre for meget kode, men du kan ændre dit skema en lille smule, kan du overveje at oprette 128-bit hashes til dine strengkolonner (ved hjælp af MD5-funktion ). I dette tilfælde (i modsætning til normalisering) behøver du ikke at ændre alle dine forespørgsler, kun INSERT'erne og nogle af SELECT'erne. I hvert fald vil du gerne hash dine strengfelter og derefter oprette et indeks på hasherne, f.eks.

CREATE INDEX ix_temp ON relations (relation_title_hash, object_title_hash);

Bemærk, at du bliver nødt til at lege med SELECT for at sikre, at du udfører beregningen via hash-indekset og ikke trækker det klyngede indeks ind (kræves for at løse den faktiske tekstværdi af object_title for at tilfredsstille forespørgslen).

Desuden, hvis relation_title har en lille varchar-størrelse, men objekttitel har en lang størrelse, kan du potentielt kun hash-haske objekt_titel og oprette indekset på (relation_title, object_title_hash) .

Bemærk, at denne løsning kun hjælper, hvis et eller begge af disse felter er meget lange i forhold til størrelsen af ​​hasherne.

Bemærk også, at der er interessante indvirkninger på store og små bogstaver/sorteringspåvirkninger fra hashing, da hash for en streng med små bogstaver ikke er det samme som en hash af en stor bogstav. Så du skal sikre dig, at du anvender kanonisering på strengene, før du hashgør dem - med andre ord, kun hash med små bogstaver, hvis du er i en DB, hvor der ikke er store og små bogstaver. Du vil måske også trimme mellemrum fra begyndelsen eller slutningen, afhængigt af hvordan din DB håndterer førende/efterliggende mellemrum.



  1. Opret en partitioneret tabel i SQL Server (T-SQL)

  2. Er det vigtigt at lukke mysql-forbindelsen?

  3. Unikke IP'er i et afstemningssystem

  4. Loop over matrixdimension i plpgsql