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

Korrekt indeksering ved brug af OR-operator

Du misforstår, hvordan indekser fungerer.

Tænk på en telefonbog (svarende til et to-kolonne indeks på efternavn for, fornavn efter). Hvis jeg beder dig finde alle personer i telefonbogen, hvis efternavn er "Smith", kan du drage fordel af, at navnene er ordnet på den måde; du kan antage, at Smiths er organiseret sammen. Men hvis jeg beder dig finde alle de personer, hvis fornavn er "John", får du ingen fordel af indekset. Johns kan have et hvilket som helst efternavn, og så er de spredt ud over bogen, og du ender med at skulle søge den hårde vej, fra ende til anden.

Hvis jeg nu beder dig om at finde alle personer, hvis efternavn er "Smith" ELLER hvis fornavn er "John", kan du nemt finde Smiths som før, men det hjælper dig overhovedet ikke med at finde Johns. De er stadig spredt ud over bogen, og du skal søge efter dem på den hårde måde.

Det er det samme med indekser med flere kolonner i SQL. Indekset er sorteret efter den første kolonne, derefter sorteret efter den anden kolonne i tilfælde af ligheder i den første kolonne, derefter sorteret efter den tredje kolonne i tilfælde af ligheder i begge de første to kolonner osv. Det er ikke sorteret efter alle kolonner samtidigt. Så dit indeks med flere kolonner hjælper ikke med at gøre dine søgetermer mere effektive, bortset fra kolonnen længst til venstre i indekset.

Tilbage til dit oprindelige spørgsmål.

Opret et separat, enkelt-kolonne indeks på hver kolonne. Et af disse indekser vil være et bedre valg end de andre, baseret på MySQL's estimering af hvor mange I/O-operationer indekset vil påløbe, hvis det bruges.

Moderne versioner af MySQL har også nogle smarte ting omkring indeksfletning , så forespørgslen kan brug mere end ét indeks i en given tabel, og prøv derefter at flette resultaterne. Ellers har MySQL en tendens til at være begrænset til at bruge ét indeks pr. tabel i en given forespørgsel.

Et andet trick, som mange mennesker bruger med succes, er at lave en separat forespørgsel for hver af dine indekserede kolonner (som skal bruge det respektive indeks) og derefter UNION resultaterne.

SELECT fields FROM table WHERE field1='something' 
UNION
SELECT fields FROM table WHERE field2='something' 
UNION
SELECT fields FROM table WHERE field3='something' 
UNION
SELECT fields FROM table WHERE field4='something' 

En sidste observation:hvis du finder dig selv i at søge efter det samme 'something' på tværs af fire felter, bør du genoverveje, om alle fire felter faktisk er det samme, og du er skyldig i at designe en tabel, der overtræder First Normal form med gentagne grupper . Hvis det er tilfældet, hører felt1 til og med felt4 måske til i en enkelt kolonne i en undertabel. Så bliver det meget nemmere at indeksere og forespørge:

SELECT fields from table INNER JOIN child_table ON table.pk = child_table.fk
WHERE child_table.field = 'something'


  1. 3 måder at slette duplikerede rækker i SQL Server, mens du ignorerer den primære nøgle

  2. Annoncering af ClusterControl 1.7.5:Avanceret klyngevedligeholdelse og support til PostgreSQL 12 og MongoDB 4.2

  3. Ret "FEJL 1136 (21S01):Kolonneantal stemmer ikke overens med værdiantallet i række 1", når du indsætter data i MySQL

  4. Uventet @@rowcount-adfærd i en UDF i MS SQL 2019