Bewerkt september 2021:ik gebruik MySQL 8.0 nu al een paar jaar, dus hier is wat bijgewerkte informatie.
De MySQL-handleiding heeft nu een zeer informatieve pagina met betrekking tot conversie tussen utf8mb3
(momenteel ook bekend als utf8
) en utf8mb4
. utf8mb3
is verouderd en wordt verwijderd
uiteindelijk; en wanneer het wordt verwijderd, de huidige alias, utf8
, zal verwijzen naar utf8mb4
in plaats daarvan.
Met verouderde utf8mb3
, kunt u maximaal 255 tekens in een index opslaan, terwijl u met utf8mb4
, tot 191, bij gebruik van COMPACT
of REDUNDANT
rij-indeling.
Met COMPRESSED
of DYNAMIC
rij-indeling, indexsleutelprefixen kunnen maximaal 3072 bytes zijn. Hiermee kunt u tot 1024 tekens indexeren voor utf8mb3
, en 768 tekens voor utf8mb4
.
Hieronder staat mijn eerdere antwoord, waarin een deel van de logica achter het aantal tekens wordt uitgelegd u kunt indexeren versus het aantal bytes .
Ik moet mijn antwoord herzien vanwege mijn onderzoek. Ik heb dit oorspronkelijk gepost (ik citeer mezelf):
Ik denk dat het antwoord is dat je niet kunt weten hoeveel tekens er in de index zullen staan, omdat je niet kunt weten hoeveel bytes je tekens zullen zijn (tenzij je iets doet om multi-byte tekens uit te sluiten).
En ik weet het niet zeker, maar het kan nog steeds correct zijn, maar niet helemaal zoals ik dacht.
Hier is het juiste antwoord:
MySQL gaat uit van 3 bytes per utf8-teken. 255 tekens is de maximale indexgrootte die u per kolom kunt opgeven, omdat 256x3=768 de limiet van 767 bytes overschrijdt.
Als u geen indexgrootte opgeeft, kiest MySQL de maximale grootte (d.w.z. 255 per kolom). Een UNIEKE beperking kan niet worden geplaatst op een utf8-kolom waarvan de lengte groter is dan 255, omdat een unieke index de volledige celwaarde moet bevatten. Maar een gewone index kan worden gebruikt - deze indexeert alleen de eerste 255 tekens (of de eerste 767 bytes?). En dat is waar er voor mij nog een mysterie is.
Het mysterie:ik begrijp waarom MySQL uit veiligheidsoverwegingen uitgaat van 3 bytes per teken, omdat anders de UNIEKE beperking zou kunnen worden doorbroken. Maar de documenten lijken te suggereren dat de index eigenlijk in bytes is, niet in tekens. Dus stel dat je een 255 . plaatst char (765 byte) index op een varchar(256 ) kolom. Als de tekens die u opslaat allemaal ASCII-tekens van 1 byte zijn, zoals A-Z, a-z, 0-9, dan past u de hele kolom in de 767-byte-index. En het lijkt erop dat dat ook daadwerkelijk zou gebeuren.
Hieronder vindt u wat meer informatie uit mijn oorspronkelijke antwoord over tekens, bytes, enz.
Volgens wikipedia , UTF-8-tekens kunnen 1,2, 3 of 4 bytes lang zijn. Maar volgens deze mysql-documentatie , de maximale tekengrootte is 3 bytes, en dus kan elke kolomindexindex van meer dan 255 tekens die bytelimiet bereiken. Maar zoals ik het begrijp, misschien niet. Als de meeste van uw tekens zich in het ASCII-bereik bevinden, ligt uw gemiddelde tekengrootte dichter bij 1 byte. Als uw gemiddelde tekengrootte bijvoorbeeld 1,3 bytes is (meestal 1 byte, maar een aanzienlijk aantal tekens van 2-3 bytes), kunt u een index van 767/1,3 opgeven.
Dus als u voornamelijk 1-byte tekens opslaat, zou uw werkelijke tekenlimiet meer zijn als:767 / 1,3 =590. Maar het blijkt dat dit niet de manier is waarop het werkt. 255 tekens is de limiet.
Zoals vermeld in deze MySQL-documentatie ,
Prefixlimieten worden gemeten in bytes, terwijl de prefixlengte in CREATE INDEX-instructies wordt geïnterpreteerd als het aantal tekens voor niet-binaire gegevenstypen (CHAR, VARCHAR, TEXT). Houd hier rekening mee bij het specificeren van een prefixlengte voor een kolom die een multi-bytetekenset gebruikt.
Het lijkt erop dat MySQL mensen adviseert om een berekening/schatting uit te voeren zoals ik net deed om je sleutelgrootte voor een varchar-kolom te bepalen. Maar in feite kun je niet specificeer een index groter dan 255 voor utf8-kolommen.
Tot slot, als je weer naar mijn tweede link verwijst, is er ook dit:
Wanneer de configuratieoptie innodb_large_prefix is ingeschakeld, wordt deze lengtelimiet verhoogd tot 3072 bytes voor InnoDB-tabellen die de rij-indelingen DYNAMIC en COMPRESSED gebruiken.
Dus het lijkt erop dat je veel grotere indexen kunt krijgen als je wilt, met een beetje tweaken. Zorg ervoor dat de rij-indelingen DYNAMISCH of GECOMPRIMEERD zijn. U kunt in dat geval waarschijnlijk een index van 1023 of 1024 tekens opgeven.
Trouwens, het blijkt dat je 4-byte tekens kunt opslaan met [de utf8mb4-tekenset][4]. De utf8-tekenset slaat blijkbaar alleen ["vlak 0"-tekens][5] op.BEWERKEN:
Ik heb zojuist geprobeerd een samengestelde index te maken op een varchar (511)-kolom met een tinyint(1)-kolom en kreeg de foutmelding dat de maximale indexgrootte 767 bytes was. Dit doet me geloven dat MySQL ervan uitgaat dat kolommen met utf8-tekensets 3 bytes per teken bevatten (het maximum), en dat je maximaal 255 tekens kunt gebruiken. Maar misschien is dat alleen bij samengestelde indexen. Ik zal mijn antwoord bijwerken als ik meer weet. Maar voor nu laat ik dit als een bewerking.