Er det noen forskjeller i ytelse mellom utf8_general_ci
og utf8_unicode_ci
?
Disse to kollasjonene er begge for UTF-8-tegnskodingen. Forskjellene ligger i hvordan tekst sorteres og sammenlignes.
Merk: Du bør bruke utf8mb4
i stedet for utf8
. Begge refererer til UTF-8-kodingen, men den eldre utf8
hadde en MySQL-spesifikk begrensning som forhindret bruk av tegn nummerert over 0xFFFD.
Merk: Nyere versjoner av MySQL har oppdaterte Unicode-sorteringsregler, tilgjengelige under navn som utf8mb4_0900_ci
for regler basert på Unicode 9.0 - og uten en tilsvarende generell
variant.
**De viktigste forskjellene
utf8mb4_unicode_ci
er basert på de offisielle Unicode-reglene for universell sortering og sammenligning, som sorterer nøyaktig på en lang rekke språk.utf8mb4_general_ci
er et forenklet sett med sorteringsregler som tar sikte på å gjøre så godt den kan, samtidig som den tar mange snarveier for å øke hastigheten. Det følger ikke Unicode-reglene og vil føre til uønsket sortering eller sammenligning i enkelte situasjoner, for eksempel ved bruk av bestemte språk eller tegn.
På moderne servere vil denne ytelsesøkningen være så godt som ubetydelig. Den ble utviklet i en tid da servere hadde en brøkdel av CPU-ytelsen til dagens datamaskiner.
*NB: Det finnes nå en oppdatert versjon av utf8mb4_unicode_ci
kalt utf8mb4_0900_ai_ci
- denne er basert på endringer i Unicode versjon 9.0, og er tilsynelatende også raskere. Den tar i bruk et nytt navneskjema der 0900
er Unicode-versjonen og ai
betyr aksent-ufølsom - i likhet med den tidligere utf8mb4_unicode_ci
regnes ikke aksenter i bokstaver som viktige.
Fordeler med utf8mb4_unicode_ci
fremfor utf8mb4_general_ci
.
utf8mb4_unicode_ci
, som bruker Unicode-reglene for sortering og sammenligning, benytter en ganske kompleks algoritme for korrekt sortering på en lang rekke språk og ved bruk av en lang rekke spesialtegn. Disse reglene må ta hensyn til språkspesifikke konvensjoner; det er ikke alle som sorterer tegnene sine i det vi vil kalle "alfabetisk rekkefølge".
Når det gjelder latinske (dvs. "europeiske") språk, er det ikke stor forskjell på Unicode-sorteringen og den forenklede utf8mb4_general_ci
-sorteringen i MySQL, men det er likevel noen forskjeller:utf8mb4_general_ci
sorterer dem som enkelttegn (antagelig som henholdsvis "s" og "e").utf8mb4_unicode_ci
håndterer disse på riktig måte.
I ikke-latinske språk, for eksempel asiatiske språk eller språk med andre alfabeter, kan det være mange flere forskjeller mellom Unicode-sortering og den forenklede utf8mb4_general_ci
-sorteringen. Hvor egnet utf8mb4_general_ci
er, avhenger i stor grad av hvilket språk som brukes. For noen språk vil den være helt utilstrekkelig.
Hva bør du bruke?
Det er nesten ingen grunn til å bruke utf8mb4_general_ci
lenger, siden vi har forlatt det punktet der CPU-hastigheten er lav nok til at ytelsesforskjellen er viktig. Databasen din vil nesten helt sikkert være begrenset av andre flaskehalser enn dette.
Tidligere var det noen som anbefalte å bruke utf8mb4_general_ci
unntatt når nøyaktig sortering var viktig nok til å rettferdiggjøre ytelseskostnaden. I dag har denne ytelseskostnaden så godt som forsvunnet, og utviklere tar internasjonalisering mer på alvor.
Det kan argumenteres for at hvis hastighet er viktigere enn nøyaktighet, kan du like gjerne la være å sortere i det hele tatt. Det er trivielt å gjøre en algoritme raskere hvis den ikke trenger å være nøyaktig. Så utf8mb4_general_ci
er et kompromiss som sannsynligvis ikke er nødvendig av hastighetsgrunner og sannsynligvis heller ikke egnet av nøyaktighetsgrunner.
En annen ting jeg vil legge til, er at selv om du vet at applikasjonen din bare støtter engelsk, kan den likevel ha behov for å håndtere personnavn, som ofte kan inneholde tegn som brukes på andre språk der det er like viktig å sortere riktig. Hvis du bruker Unicode-reglene for alt, kan du være trygg på at de smarte Unicode-folkene har jobbet hardt for å få sorteringen til å fungere skikkelig.
Hva delene betyr
For det første er ci
for case-insensitive sortering og sammenligning. Det betyr at den egner seg for tekstdata der store og små bokstaver ikke er viktige. De andre sorteringstypene er cs
(store og små bokstaver) for tekstdata der store og små bokstaver er viktige, og bin
, der kodingen må samsvare bit for bit, som egner seg for felt som egentlig er kodede binære data (inkludert for eksempel Base64). Sortering med hensyn til store og små bokstaver fører til underlige resultater, og sammenligning med hensyn til store og små bokstaver kan resultere i dupliserte verdier som bare skiller seg fra hverandre i store og små bokstaver, så kollasjoner med hensyn til store og små bokstaver er i ferd med å falle i unåde for tekstdata - hvis store og små bokstaver er viktig for deg, er sannsynligvis også tegnsetting og så videre viktig, og en binær kollasjon kan være mer passende.
Deretter refererer unicode
eller general
til de spesifikke sorterings- og sammenligningsreglene - spesielt måten tekst normaliseres eller sammenlignes på. Det finnes mange forskjellige regelsett for utf8mb4-tegnkodingen, og unicode
og general
er to av dem som forsøker å fungere godt på alle mulige språk i stedet for på ett bestemt språk. Forskjellene mellom disse to regelsettene er temaet for dette svaret. Merk at unicode
bruker regler fra Unicode 4.0. Nyere versjoner av MySQL har lagt til regelsettene unicode_520
som bruker regler fra Unicode 5.2, og 0900
(uten "unicode_") som bruker regler fra Unicode 9.0.
Og til slutt, utf8mb4
er selvfølgelig tegnkodingen som brukes internt. I dette svaret snakker jeg kun om Unicode-baserte kodinger.Dette innlegget beskriver det veldig godt.
Kort sagt: utf8_unicode_ci bruker Unicode Collation Algorithm som definert i Unicode-standardene, mens utf8_general_ci er en enklere sorteringsrekkefølge som gir "mindre nøyaktige" sorteringsresultater.
Se mysql-manualen, avsnittet Unicode-tegnsett: For alle Unicode-tegnsett,
operasjoner som utføres ved hjelp av _general_ci-sorteringen raskere enn de som utføres med _unicode_ci-sorteringen. For eksempel er sammenligninger for tegnsettet utf8_general_ci-sorteringen raskere, men litt mindre korrekte enn sammenligninger for utf8_unicode_ci. Årsaken grunnen til dette er at utf8_unicode_ci støtter mappinger som f.eks. som ekspansjoner, det vil si at når ett tegn tegn sammenlignes som lik kombinasjoner av andre tegn. For eksempel eksempel, på tysk og noen andre språk er språk er for eksempel "ß" lik "ss". utf8_unicode_ci støtter også sammentrekninger og tegn som ikke kan ignoreres. utf8_general_ci er en eldre sortering som ikke støtter utvidelser, sammentrekninger eller tegn som ikke kan ignoreres. Den kan bare foreta én-til-én-sammenligninger sammenligninger mellom tegn.
Så for å oppsummere bruker utf_general_ci et mindre og mindre korrekt (i henhold til standarden) sett med sammenligninger enn utf_unicode_ci, som skal implementere hele standarden. General_ci-settet vil være raskere fordi det er mindre beregning å gjøre.