Entre utf8_general_ci
et utf8_unicode_ci
, y a-t-il des différences en termes de performances ?
Ces deux collations sont toutes deux destinées au codage des caractères UTF-8. Les différences résident dans la façon dont le texte est trié et comparé.
Note : Vous devriez utiliser utf8mb4
plutôt que utf8
. Les deux font référence à l'encodage UTF-8, mais l'ancien utf8
avait une limitation spécifique à MySQL empêchant l'utilisation de caractères numérotés au-dessus de 0xFFFD.
*Remarque : les versions plus récentes de MySQL ont des règles de tri Unicode mises à jour, disponibles sous des noms tels que utf8mb4_0900_ci
pour les règles basées sur Unicode 9.0 - et sans variante general
équivalente.
Principales différences
utf8mb4_unicode_ci
est basé sur les règles officielles d'Unicode pour le tri et la comparaison universels, qui trient avec précision dans une large gamme de langues.utf8mb4_general_ci
est un ensemble simplifié de règles de tri qui vise à faire aussi bien que possible tout en prenant de nombreux raccourcis conçus pour améliorer la vitesse. Il ne suit pas les règles Unicode et entraînera un tri ou une comparaison indésirable dans certaines situations, comme l'utilisation de langues ou de caractères particuliers.
Sur les serveurs modernes, ce gain de performance sera tout sauf négligeable. Il a été conçu à une époque où les serveurs ne disposaient que d'une infime partie des performances des processeurs des ordinateurs actuels.
*Note : il existe maintenant une version mise à jour de utf8mb4_unicode_ci
appelée utf8mb4_0900_ai_ci
- elle est basée sur les changements de la version 9.0 d'Unicode, et est aussi apparemment plus rapide. Il adopte un nouveau schéma de dénomination dans lequel 0900
est la version Unicode et ai
signifie insensible aux accents - comme le précédent utf8mb4_unicode_ci
, les accents dans les lettres ne sont pas considérés comme significatifs.
Avantages de utf8mb4_unicode_ci' par rapport à
utf8mb4_general_ci' .
utf8mb4_unicode_ci
, qui utilise les règles Unicode pour le tri et la comparaison, emploie un algorithme assez complexe pour un tri correct dans une large gamme de langues et lors de l'utilisation d'un large éventail de caractères spéciaux. Ces règles doivent tenir compte des conventions propres à chaque langue ; tout le monde ne trie pas ses caractères dans ce que nous appellerions l'"ordre alphabétique".
En ce qui concerne les langues latines (c'est-à-dire "européennes"), il n'y a pas beaucoup de différence entre le tri Unicode et le tri simplifié utf8mb4_general_ci
de MySQL, mais il y a quand même quelques différences :utf8mb4_general_ci
les trie comme des caractères uniques (vraisemblablement comme "s" ; et "e" ; respectivement).utf8mb4_unicode_ci
les gère correctement.
Dans les langues non-latines, comme les langues asiatiques ou les langues avec des alphabets différents, il peut y avoir beaucoup plus de différences entre le tri Unicode et le tri simplifié de utf8mb4_general_ci
. L'adéquation de utf8mb4_general_ci
dépendra fortement de la langue utilisée. Pour certains langages, il sera tout à fait inadéquat.
Que devriez-vous utiliser?
Il n'y a presque certainement plus de raison d'utiliser utf8mb4_general_ci
, car nous avons laissé derrière nous le point où la vitesse du CPU est suffisamment basse pour que la différence de performance soit importante. Votre base de données sera presque certainement limitée par d'autres goulots d'étranglement que celui-ci.
Dans le passé, certaines personnes recommandaient d'utiliser utf8mb4_general_ci
sauf quand un tri précis était suffisamment important pour justifier le coût des performances. Aujourd'hui, ce coût de performance a pratiquement disparu, et les développeurs traitent l'internationalisation plus sérieusement.
Il y a un argument à faire valoir : si la vitesse est plus importante pour vous que la précision, vous pouvez tout aussi bien ne pas faire de tri du tout. Il est trivial de rendre un algorithme plus rapide si vous n'avez pas besoin qu'il soit précis. Ainsi, utf8mb4_general_ci
est un compromis qui n'est probablement pas nécessaire pour des raisons de vitesse et qui ne convient probablement pas non plus pour des raisons de précision.
J'ajouterai une autre chose : même si vous savez que votre application ne prend en charge que la langue anglaise, il se peut qu'elle doive traiter des noms de personnes, qui peuvent souvent contenir des caractères utilisés dans d'autres langues et qu'il est tout aussi important de trier correctement. L'utilisation des règles d'Unicode pour tout contribue à la tranquillité d'esprit, car les personnes très intelligentes d'Unicode ont travaillé très dur pour que le tri fonctionne correctement.
*Ce que les parties signifient
Tout d'abord, ci
est pour le tri et la comparaison insensible à la casse*. Cela signifie qu'il convient aux données textuelles, et que la casse n'est pas importante. Les autres types de collation sont cs
(sensible à la casse) pour les données textuelles où la casse est importante, et bin
, pour les cas où le codage doit correspondre, bit par bit, ce qui convient aux champs qui sont vraiment des données binaires codées (y compris, par exemple, Base64). Le tri sensible à la casse conduit à des résultats étranges et la comparaison sensible à la casse peut aboutir à des valeurs dupliquées qui ne diffèrent que par la casse des lettres. Les collations sensibles à la casse sont donc de moins en moins appréciées pour les données textuelles - si la casse est importante pour vous, la ponctuation, etc. est probablement aussi importante, et une collation binaire pourrait être plus appropriée.
Ensuite, unicode
ou general
fait référence aux règles spécifiques de tri et de comparaison - en particulier, la façon dont le texte est normalisé ou comparé. Il existe de nombreux jeux de règles différents pour le codage des caractères utf8mb4, unicode
et general
étant deux jeux qui tentent de fonctionner correctement dans toutes les langues possibles plutôt que dans une seule. Les différences entre ces deux ensembles de règles sont le sujet de cette réponse. Notez que unicode
utilise les règles de Unicode 4.0. Les versions récentes de MySQL ajoutent les jeux de règles unicode_520
utilisant les règles d'Unicode 5.2, et 0900
(en supprimant la partie "unicode_" ;) utilisant les règles d'Unicode 9.0.
Et enfin, utf8mb4
est bien sûr le codage de caractères utilisé en interne. Dans cette réponse, je ne parle que des encodages basés sur Unicode.Ce billet le décrit très bien.
En résumé, utf8_unicode_ci utilise l'algorithme de collation Unicode tel que défini dans les normes Unicode, tandis que utf8_general_ci est un ordre de tri plus simple qui donne des résultats de tri " moins précis ".
Voir le manuel mysql, section [Unicode Character Sets][1] :
Pour tout jeu de caractères Unicode, les opérations effectuées en utilisant la _general_ci sont plus rapides que celles effectuées avec la collation _unicode_ci. Par exemple, les comparaisons pour le jeu de caractères utf8_general_ci sont plus rapides, mais légèrement moins correctes que comparaisons pour la collation utf8_unicode_ci. Le site La raison en est que utf8_unicode_ci supporte des mappings tels que les expansions. comme les expansions ; c'est-à-dire, lorsqu'un caractère est comparé comme étant égal à combinaisons d'autres caractères. Pour exemple, en allemand et dans certaines autres langues "ß ;" est égal à "ss". utf8_unicode_ci prend également en charge les éléments suivants les contractions et les caractères ignorables. utf8_general_ci est une ancienne collation qui ne prend pas en charge les expansions, les contractions ou les caractères ignorables. Elle ne peut effectuer que des comparaisons biunivoques entre les caractères. d'un à un entre les caractères.
Donc pour résumer, utf_general_ci utilise un ensemble de comparaisons plus petit et moins correct (selon la norme) que utf_unicode_ci qui devrait implémenter la norme entière. L'ensemble general_ci sera plus rapide car il y a moins de calculs à faire.
[1] : http://dev.mysql.com/doc/refman/5.0/en/charset-unicode-sets.html