För de personer som fortfarande kommer fram till den här frågan 2020 eller senare finns det nyare alternativ som kan vara bättre än båda av dessa. Till exempel, utf8mb4_0900_ai_ci
.
Alla dessa sorteringar är för teckenkodning UTF-8. Skillnaderna ligger i hur text sorteras och jämförs.
_unicode_ci
och _general_ci
är två olika uppsättningar regler för att sortera och jämföra text enligt det sätt vi förväntar oss. Nyare versioner av MySQL introducerar också nya uppsättningar regler, såsom _0900_ai_ci
för motsvarande regler baserade på Unicode 9.0 - och utan motsvarande _general_ci
variant. Personer som läser detta nu borde förmodligen använda någon av dessa nyare sorteringar istället för antingen _unicode_ci
eller _general_ci
. Beskrivningen av de äldre samlingarna nedan tillhandahålls endast för intresse.
MySQL håller på att övergå från en äldre, felaktig UTF-8-implementering. För närvarande måste du använda utf8mb4
istället för utf8
för teckenkodningsdelen, för att säkerställa att du får den fasta versionen. Den felaktiga versionen finns kvar för bakåtkompatibilitet, även om den håller på att fasas ut.
Nyckelskillnader
-
utf8mb4_unicode_ci
är baserad på de officiella Unicode-reglerna för universell sortering och jämförelse, som sorterar exakt på ett stort antal språk. -
utf8mb4_general_ci
är en förenklad uppsättning sorteringsregler som syftar till att göra så bra den kan samtidigt som man tar många genvägar för att förbättra hastigheten. Det följer inte Unicode-reglerna och kommer att resultera i oönskad sortering eller jämförelse i vissa situationer, till exempel när du använder särskilda språk eller tecken.På moderna servrar kommer denna prestandaökning att vara nästan försumbar. Det skapades i en tid då servrar hade en liten bråkdel av CPU-prestanda hos dagens datorer.
Fördelar med utf8mb4_unicode_ci
över utf8mb4_general_ci
utf8mb4_unicode_ci
, som använder Unicode-reglerna för sortering och jämförelse, använder en ganska komplex algoritm för korrekt sortering på ett brett spektrum av språk och vid användning av ett brett spektrum av specialtecken. Dessa regler måste ta hänsyn till språkspecifika konventioner; alla sorterar inte sina karaktärer i vad vi skulle kalla "alfabetisk ordning".
När det gäller latinska (dvs. "europeiska") språk är det inte stor skillnad mellan Unicode-sortering och den förenklade utf8mb4_general_ci
sortering i MySQL, men det finns fortfarande några skillnader:
-
Till exempel sorterar Unicode-sorteringen "ß" som "ss" och "Œ" som "OE" som personer som använder dessa tecken normalt skulle vilja, medan
utf8mb4_general_ci
sorterar dem som enstaka tecken (förmodligen som "s" respektive "e"). -
Vissa Unicode-tecken definieras som ignorerbara, vilket innebär att de inte ska räknas mot sorteringsordningen och jämförelsen bör gå vidare till nästa tecken istället.
utf8mb4_unicode_ci
hanterar dessa på rätt sätt.
På icke-latinska språk, som asiatiska språk eller språk med olika alfabet, kan det finnas mycket mer skillnader mellan Unicode-sortering och den förenklade utf8mb4_general_ci
sortering. Lämpligheten för utf8mb4_general_ci
kommer att bero mycket på vilket språk som används. För vissa språk kommer det att vara ganska otillräckligt.
Vad ska du använda?
Det finns nästan säkert ingen anledning att använda utf8mb4_general_ci
längre, eftersom vi har lämnat den punkt där CPU-hastigheten är tillräckligt låg för att prestandaskillnaden skulle vara viktig. Din databas kommer nästan säkert att begränsas av andra flaskhalsar än detta.
Tidigare rekommenderade vissa människor att använda utf8mb4_general_ci
förutom när noggrann sortering skulle vara tillräckligt viktig för att motivera prestationskostnaden. Idag har den prestationskostnaden nästan försvunnit, och utvecklare tar internationalisering på större allvar.
Det finns ett argument att framföra att om hastighet är viktigare för dig än noggrannhet, kan du lika gärna inte göra någon sortering alls. Det är trivialt att göra en algoritm snabbare om du inte behöver den för att vara korrekt. Så, utf8mb4_general_ci
är en kompromiss som förmodligen inte behövs av hastighetsskäl och förmodligen inte heller lämplig av exakthetsskäl.
En annan sak som jag ska tillägga är att även om du vet att din applikation bara stöder det engelska språket, kan den fortfarande behöva hantera personers namn, som ofta kan innehålla tecken som används på andra språk där det är lika viktigt att sortera rätt. . Att använda Unicode-reglerna för allt bidrar till att skapa sinnesfrid att de mycket smarta Unicode-folket har arbetat mycket hårt för att få sorteringen att fungera korrekt.
Vad delarna betyder
För det första, ci
är för skiftlägesokänslig sortering och jämförelse. Detta betyder att det är lämpligt för textdata, och skiftläge är inte viktigt. De andra typerna av sortering är cs
(skiftlägeskänslig) för textdata där skiftläge är viktigt, och bin
, för där kodningen behöver matcha, bit för bit, vilket är lämpligt för fält som verkligen är kodade binära data (inklusive till exempel Base64). Skiftlägeskänslig sortering leder till några konstiga resultat och skiftlägeskänslig jämförelse kan resultera i att dubbletter av värden skiljer sig endast i skiftläge, så skiftlägeskänsliga sorteringar faller i onåd för textdata - om skiftläge är viktigt för dig, då annars ignorerbar interpunktion och så vidare är förmodligen också signifikant, och en binär sammanställning kan vara mer lämplig.
Därefter unicode
eller general
hänvisar till de specifika sorterings- och jämförelsereglerna - i synnerhet hur text normaliseras eller jämförs. Det finns många olika uppsättningar regler för teckenkodningen utf8mb4, med unicode
och general
att vara två som försöker fungera bra på alla möjliga språk snarare än ett specifikt. Skillnaderna mellan dessa två uppsättningar regler är ämnet för detta svar. Observera att unicode
använder regler från Unicode 4.0. Senaste versioner av MySQL lägger till regeluppsättningarna unicode_520
använder regler från Unicode 5.2 och 0900
(släpper "unicode_"-delen) med regler från Unicode 9.0.
Och slutligen, utf8mb4
är naturligtvis teckenkodningen som används internt. I det här svaret talar jag bara om Unicode-baserade kodningar.