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

Fuldtekst og sammensatte indekser og hvordan de påvirker forespørgslen

Hvis jeg forstår dit spørgsmål, ved du, at MATCH AGAINST bruger dit FULLTEXT-indeks, og du undrer dig over, hvordan MySQL går med at anvende resten af ​​WHERE-sætningen (dvs. laver den en tabelscanning eller et indekseret opslag).

Her er, hvad jeg antager om din tabel:den har en PRIMÆR NØGLE på en id-kolonne og FULLTEXT-indekset.

Så først og fremmest vil MySQL aldrig brug FULLTEXT-indekset for by/stat WHERE-klausulen. Hvorfor? Fordi FULLTEXT-indekser kun gælder med MATCH MOD. Se her i afsnittet efter det første sæt punkttegn (ikke indholdsfortegnelsen punkttegn).

EDIT: I dit tilfælde, forudsat at din tabel ikke kun har 10 rækker, vil MySQL anvende FULLTEXT-indekset for din MATCH MOD, og ​​derefter foretage en tabelscanning på disse resultater for at anvende byen/staten WHERE.

Så hvad hvis du tilføjer et BTREE-indeks til by og stat?

CREATE INDEX city__state ON table (city(10),state(2)) USING BTREE;

Nå, MySQL kan kun bruge én indeks for denne forespørgsel, da det er et simpelt valg. Det vil enten brug FULLTEXT eller BTRÆET. Bemærk, at når jeg siger ét indeks, mener jeg én indeksdefinition, ikke én kolonne i et flerdelt indeks. Anwway, dette rejser så spørgsmålet, hvem man gør bruger den?

Det afhænger af tabelanalysen. MySQL vil forsøge at estimere (baseret på tabelstatistik fra den sidste OPTIMER-TABEL), hvilket indeks vil beskære flest poster. Hvis byen/staten WHERE får dig ned på 10 poster, mens MATCH MOD kun får dig ned på 100, så vil MySQL bruge city__state indekset først for byen/staten HVOR og lav derefter en tabelscanning for KAMP MOD.

På den anden side, hvis MATCH_AGAINST får dig ned på 10 poster, mens byen/staten WHERE kun får dig ned på 1000, så vil MySQL anvende FULLTEXT-indekset først og tablescan for by og stat.

Den nederste linje er kardinaliteten af dit indeks. I bund og grund, hvor unikke er de værdier, der vil indgå i dit indeks? Hvis hver post i din tabel har byen sat til Oakland, så er det ikke en særlig unik nøgle, og derfor har by ='Oakland' reducerer faktisk ikke antallet af poster så meget for dig. I så fald siger vi, at dit by_statsindeks har en lav kardinalitet .

Derfor, hvis 90 % af ordene i dit FULLTEXT-indeks er "John", så hjælper det dig heller ikke meget af nøjagtig samme årsager.

Hvis du har råd til pladsen og UPDATE/DELETE/INSERT overhead, vil jeg anbefale at tilføje BTREE indekset og lade MySQL bestemme hvilket indeks han vil bruge. Efter min erfaring gør han normalt et meget godt stykke arbejde med at vælge den rigtige.

Jeg håber, det besvarer dit spørgsmål.

EDIT: Som en sidebemærkning skal du sørge for at vælge den rigtige størrelse til dit BTREE-indeks (i mit eksempel valgte jeg de første 10 char i byen). Dette har naturligvis en enorm indflydelse på kardinalitet. Hvis du valgte by(1), vil du naturligvis få en lavere kardinalitet end hvis du valgte by(10).

EDIT2: MySQL's forespørgselsplan (estimat), for hvilket indeks, der beskærer flest poster, er det, du ser i EXPLAIN.



  1. Returner slutningen af ​​måneden i SQLite

  2. Hvad er databasen, hvorfor databasen?

  3. SQL SERVER - Forstå hvordan MIN(tekst) virker

  4. Grupper for måned inklusive tomme måneder