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

MySQL varchar indekslængde

Sept 2021 edit:Jeg har brugt MySQL 8.0 i et par år nu, så her er nogle opdaterede oplysninger.

MySQL-manualen har nu en meget informativ side vedrørende konvertering mellem utf8mb3 (i øjeblikket også kendt som utf8 ) og utf8mb4 . utf8mb3 er udfaset og vil blive fjernet til sidst; og når det fjernes, dets nuværende alias, utf8 , vil henvise til utf8mb4 i stedet.

Med forældet utf8mb3 , kan du gemme op til 255 tegn i et indeks, mens du med utf8mb4 , op til 191, når du bruger COMPACT eller REDUNDANT rækkeformat.

Med COMPRESSED eller DYNAMIC rækkeformat, indeksnøglepræfikser kan være op til 3072 bytes. Med dem kan du indeksere op til 1024 tegn for utf8mb3 , og 768 tegn for utf8mb4 .

Nedenfor er mit tidligere svar, som forklarer noget af logikken bag antallet af tegn du kan indeksere i forhold til antallet af bytes .

Jeg må revidere mit svar på grund af min research. Jeg postede oprindeligt dette (citerer mig selv):

Jeg tror, ​​at svaret er, at du ikke kan vide, hvor mange tegn der vil være i indekset, fordi du ikke kan vide, hvor mange bytes dine tegn vil være (medmindre du gør noget for at udelukke multi-byte tegn).

Og jeg er ikke sikker, men det kan stadig være korrekt, men ikke helt på den måde, jeg havde tænkt mig.

Her er det rigtige svar:

MySQL antager 3 bytes pr. utf8-tegn. 255 tegn er den maksimale indeksstørrelse, du kan angive pr. kolonne, fordi 256x3=768, hvilket bryder grænsen på 767 byte.

Hvis du ikke angiver indeksstørrelse, vælger MySQL den maksimale størrelse (dvs. 255 pr. kolonne). En UNIK begrænsning kan ikke sættes på en utf8-kolonne, hvis længde er større end 255, fordi et unikt indeks skal indeholde hele celleværdien. Men et almindeligt indeks kan bruges - det vil blot indeksere de første 255 tegn (eller de første 767 bytes?). Og det er der, der stadig er noget mystik for mig.

MySTERIET:Jeg kan se, hvorfor MySQL antager 3 bytes pr. tegn, for sikkerheds skyld, for ellers kunne den UNIKKE begrænsning blive brudt. Men dokumenterne synes at antyde, at indekset faktisk er størrelsen i bytes, ikke tegn. Så antag, at du sætter en 255 char (765 byte) indeks på en varchar(256 ) kolonne. Hvis de tegn, du gemmer, alle er ASCII, 1-byte-tegn, som A-Z, a-z, 0-9, så kan du passe hele kolonnen ind i 767 byte-indekset. Og det ser ud til, at det er det, der rent faktisk ville ske.

Nedenfor er nogle flere oplysninger fra mit originale svar om tegn, bytes osv.

Ifølge wikipedia , UTF-8-tegn kan være 1,2, 3 eller 4 bytes langt. Men ifølge denne mysql-dokumentation , den maksimale tegnstørrelse er 3 bytes, og så ethvert kolonneindeksindeks over 255 tegn kan ramme denne bytegrænse. Men som jeg forstår det, er det måske ikke. Hvis de fleste af dine tegn er i ASCII-området, vil din gennemsnitlige tegnstørrelse være tættere på 1 byte. Hvis din gennemsnitlige tegnstørrelse for eksempel er 1,3 byte (for det meste 1 byte, men et betydeligt antal på 2-3 byte tegn), så kan du angive et indeks på 767/1,3

Så hvis du for det meste gemmer 1-byte tegn, ville din faktiske tegngrænse være mere som:767 / 1,3 =590. Men det viser sig, at det ikke er sådan, det fungerer. 255 tegn er grænsen.

Som nævnt i denne MySQL-dokumentation ,

Præfiksgrænser måles i bytes, hvorimod præfikslængden i CREATE INDEX-sætninger fortolkes som antallet af tegn for ikke-binære datatyper (CHAR, VARCHAR, TEXT). Tag dette i betragtning, når du angiver en præfikslængde for en kolonne, der bruger et multi-bytetegnsæt.

Det ser ud til, at MySQL råder folk til at lave en beregning/gæst, som jeg lige har gjort, for at bestemme din nøglestørrelse for en varchar-kolonne. Men faktisk kan du ikke angiv et indeks større end 255 for utf8-kolonner.

Til sidst, hvis du henviser tilbage til mit andet link igen, er der også dette:

Når konfigurationsindstillingen innodb_large_prefix er aktiveret, hæves denne længdegrænse til 3072 bytes for InnoDB-tabeller, der bruger DYNAMIC og COMPRESSED rækkeformaterne.

Så det ser ud til, at du kan få meget større indekser, hvis du vil, med en smule tweaking. Bare sørg for, at rækkeformaterne er DYNAMISKE eller KOMPRESSERTE. Du kan sikkert angive et indeks på 1023 eller 1024 tegn i så fald.

Det viser sig i øvrigt, at du kan gemme 4-byte-tegn ved hjælp af [utf8mb4-tegnsættet][4]. Utf8-tegnsættet gemmer tilsyneladende kun ["plan 0"-tegn][5].

EDIT:

Jeg prøvede lige at oprette et sammensat indeks på en varchar(511) kolonne med en tinyint(1) kolonne og fik fejlmeddelelsen om, at den maksimale indeksstørrelse var 767 bytes. Dette får mig til at tro, at MySQL antager, at utf8-tegnsætkolonner vil indeholde 3 bytes pr. tegn (det maksimale), og giver dig mulighed for at bruge max. 255 tegn. Men det er måske kun med sammensatte indekser. Jeg vil opdatere mit svar, når jeg finder ud af mere. Men indtil videre forlader jeg dette som en redigering.



  1. Implementering af MariaDB-replikering for høj tilgængelighed

  2. Oracle opdelt bord

  3. Sådan administrerer du din database med Adminer

  4. SQL Dev 4.2 Top SQL