2017-09-20 8 views
1

Actuellement j'utilise VARCHAR/TEXT avec utf8_general_ci pour toutes les colonnes de caractères dans mysql. Maintenant, je veux améliorer la mise en page/performance de la base de données.Jeu de caractères suggéré pour les colonnes non utf8 dans mysql

Ce que je pensais à ce jour est de mieux utiliser

  • CHAR au lieu de VARCHAR pour les colonnes de longueur fixe comme GUIDs ou une session ids
  • utilisent également CHAR pour les petites colonnes ayant une longueur de 1 ou peut-être 2?

Comme je ne veux pas aller aussi large pour sauver mes GUIDs comme BINARY(16) en raison de problèmes de manipulation, je préfère les enregistrer comme CHAR(32) pour améliorer en particulier les clés. (Je sauverais même les 2/3 en passant de utf8 à un jeu de caractères de 1 octet)

  • Alors quel sera le meilleur jeu de caractères pour de telles colonnes? ASCII? latin1? BINAIRE? Quelle collation?
  • Quel caractère/collation utiliser pour les autres colonnes où je n'ai pas besoin du support utf8 mais qui nécessite un tri approprié. Un binaire échouerait?

Est-ce une bonne pratique de mélanger différents jeux de caractères dans la même table mysql (innodb)? Ou est-ce que j'obtiens de meilleures performances quand toutes les colonnes ont le même charset dans la même table? Ou même la base de données?

+0

UTF-8 utilise seulement plus d'un octet si le caractère est en dehors de la plage ASCII. Les UUID stringifiés (si c'est ce que vous utilisez comme GUID) tombent toujours dans cette plage. – robertklep

+0

@robertklep J'ai entendu cela et cela a du sens, mais je pense que cela ne s'applique pas à l'index (consommation d'espace) !? Par exemple, un 'EXPLAIN SELECT' montre une valeur de' key_len' 2/3 plus petite lors de la conversion de la colonne utf8 en latin1 – toshniba

+0

Ah, je n'en ai pas tenu compte (je ne sais pas comment les index MySQL/InnoDB sont implémentés). – robertklep

Répondre

1

GUID/UUID/MD5/SHA1 sont tous hex et tiret. Pour les

CHAR(..) CHARACTER SET ascii COLLATE ascii_general_ci 

Cela permettra A = a lorsque l'on compare les chaînes hexagonales.

Pour les choses base64, utilisez l'une des

CHAR(..) CHARACTER SET ascii COLLATE ascii_bin 
BINARY(..) 

depuis A est pas sémantiquement la même chose que a.

Notes complémentaires ...

  • UTF8 crache dessus si vous donnez une valeur de 8 bits non valide. Ascii crache sur vous pour toute valeur de 8 bits.
  • Latin1 accepte n'importe quoi - ainsi vos problèmes sur la route
  • Il est tout à fait correct d'avoir différentes colonnes dans une table ayant des charsets et/ou des collations différents.
  • Le jeu de caractères/classement sur la table est juste un par défaut, qui peut être remplacé par la définition de colonne.
  • BINARY peut être un peu plus rapide que n'importe quel _bin classement, mais pas assez pour remarquer.
  • Utilisez CHAR pour les colonnes dont la longueur est réellement fixe; n'induisez pas l'utilisateur en erreur en l'utilisant pour d'autres cas.
  • %_bin est plus rapide que %_general_ci, ce qui est plus rapide que d'autres classements.Encore une fois, vous auriez du mal à mesurer une différence.
  • N'utilisez jamais TINYTEXT ou TINYBLOB.
  • Pour un codage correct, utilisez le jeu de caractères approprié.
  • Pour un "tri correct", utilisez le classement approprié. Voir l'exemple ci-dessous.
  • Pour un «tri correct» lorsque plusieurs langues sont représentées et que vous utilisez,, utilisez utf8mb4_unicode_520_ci (ou utf8mb4_900_ci si vous utilisez la version 8.0). Les 520 et 900 se réfèrent aux normes Unicode; de nouvelles collations sont susceptibles de venir dans le futur.

Si vous êtes entièrement en tchèque, considérez ces charsets et collations. Je leur liste dans l'ordre préféré:

mysql> show collation like '%czech%'; 
+------------------+---------+-----+---------+----------+---------+ 
| Collation  | Charset | Id | Default | Compiled | Sortlen | 
+------------------+---------+-----+---------+----------+---------+ 
| utf8mb4_czech_ci | utf8mb4 | 234 |   | Yes  |  8 | -- opens up the world 
| utf8_czech_ci | utf8 | 202 |   | Yes  |  8 | -- opens up most of the world 
| latin2_czech_cs | latin2 | 2 |   | Yes  |  4 | -- kinda like latin1 

Les autres sont "inutiles":

| cp1250_czech_cs | cp1250 | 34 |   | Yes  |  2 | 
| ucs2_czech_ci | ucs2 | 138 |   | Yes  |  8 | 
| utf16_czech_ci | utf16 | 111 |   | Yes  |  8 | 
| utf32_czech_ci | utf32 | 170 |   | Yes  |  8 | 
+------------------+---------+-----+---------+----------+---------+ 
7 rows in set (0.00 sec) 

Plus

  • La raison d'utiliser des types de données plus petits (le cas échéant) est de réduire l'ensemble de données, ce qui conduit à moins d'E/S, ce qui conduit à des choses plus susceptibles d'être mises en cache, ce qui accélère le fonctionnement du programme. Ceci est particulièrement important pour les grands ensembles de données; il est moins important pour les ensembles de données de petite ou moyenne taille.
  • ENUM est 1 octet, mais agit comme une chaîne. Donc, vous obtenez le "meilleur des deux mondes". (Il y a des inconvénients, et il y a une «guerre religieuse» entre les défenseurs ENUM vs TINYINT vs VARCHAR.)
  • Habituellement, les colonnes qui sont «courtes» ont toujours la même longueur. Un country_code est toujours 2 lettres, toujours ascii, pourrait toujours bénéficier de la collation insensible à la casse. Donc CHAR(2) CHARACTER SET ascii COLLATE ascii_general_ci est optimal. Si vous avez quelque chose qui est parfois 1-char, parfois 2, alors lancez une pièce; quoi que vous fassiez ne fera pas beaucoup de différence.
  • VARCHAR (jusqu'à 255) a une longueur supplémentaire de 1 octet qui lui est attachée. Donc, si vos chaînes varient en longueur tout, VARCHAR est au moins aussi bon que CHAR. Alors simplifiez le traitement de votre cerveau: "longueur variable ->` VARCHAR ".
  • BIT, selon la version, peut être implémenté sous la forme d'un octet TINYINT UNSIGNED. Si vous n'avez que quelques bits dans votre table, cela ne vaut pas la peine de vous inquiéter.
  • Un de mes Rules of Thumb dit que si vous n'obtenez pas une amélioration de 10%, passez à une autre optimisation. Une grande partie de ce dont nous parlons ici est inférieure à 10% (espace dans ce cas). Toujours, prenez l'habitude d'y penser en écrivant CREATE TABLE. Je vois souvent des tables avec BIGINT et DOUBLE (chaque 8 octets) qui pourraient facilement utiliser des colonnes plus petites. Parfois, en économisant plus de 50% (espace).
  • Comment "espace" se traduit par "vitesse". Tables minuscules -> un pourcentage minuscule. Tables énormes -> Dans certains cas 10x. (C'est 10 fois, et non 10%.) (UUID sont un moyen d'obtenir des performances vraiment mauvais sur les tables énormes.)

ENUM

  • actes et se sent comme une chaîne, mais prend seulement un octet.(Un octet se traduit indirectement par une légère amélioration de la vitesse.)
  • Pratique quand moins de, disons, 10 valeurs différentes.
  • Impossible d'ajouter une nouvelle valeur - nécessite ALTER TABLE, même si peut être être "inplace".
  • Suggérer le début de la liste avec 'unknown' (ou quelque chose comme ça) et en faisant la colonne NOT NULL (contre NULL).
  • Le jeu de caractères de l'énumération doit être celui qui est utilisé pour la connexion. Le choix n'a pas beaucoup d'importance sauf si vous avez des options assembler égal (par exemple, A par rapport à a).
+0

merci beaucoup! est-il sensé d'utiliser des entiers plus petits (<4B) et des bits? J'ai entendu que mysqls 'ENUM' est une bonne pratique à utiliser? qu'en est-il des colonnes CHAR (1) et (2)? utilisez VARCHAR à la place quand certains (quel pourcentage?) ne sont pas remplis? – toshniba

+0

J'aime "ENUM" dans certaines situations; Certaines personnes ne les aiment pas. Je m'oppose 'CHAR' _except_ pour les colonnes vraiment de longueur fixe; et seulement avec le 'CHARACTER SET' approprié (qui est _usually_' ascii'). –

+0

merci @rick mais ce n'est pas vraiment utile car vous n'indiquez pas pourquoi vous "enumez" (avantages/inconvénients) et nous connaissons déjà les choses mentionnées sur les caractères. Peut-être pouvez-vous expliquer pourquoi/quand utiliser 'ENUM' a du sens (en particulier les performances) et s'il est toujours logique d'utiliser' CHAR' quand plusieurs lignes (pourcentage?) N'ont aucune valeur dans cette colonne. – toshniba