Ich frage mich, ob es in MySQL eine "beste" Auswahl für die Sortierung für eine allgemeine Website gibt, bei der Sie nicht 100% sicher sind, was eingegeben wird. Ich verstehe, dass alle Codierungen gleich sein sollten, wie MySQL, Apache, HTML und alles in PHP.
In der Vergangenheit habe ich PHP so eingestellt, dass es in "UTF-8" ausgegeben wird. Aber welche Sortierung stimmt mit dieser in MySQL überein? Ich denke , es ist eine der UTF-8 ist, aber ich verwendet habe utf8_unicode_ci
, utf8_general_ci
und utf8_bin
vor.
Antworten:
Der Hauptunterschied besteht in der Sortiergenauigkeit (beim Vergleichen von Zeichen in der Sprache) und der Leistung. Die einzige Besonderheit ist utf8_bin, mit der Zeichen im Binärformat verglichen werden können.
utf8_general_ci
ist etwas schneller alsutf8_unicode_ci
, aber weniger genau (zum Sortieren). Die spezifische utf8-Sprachcodierung (z. B.utf8_swedish_ci
) enthält zusätzliche Sprachregeln, mit denen sie für diese Sprachen am genauesten sortiert werden können. Die meiste Zeit benutze ichutf8_unicode_ci
(ich bevorzuge Genauigkeit gegenüber kleinen Leistungsverbesserungen), es sei denn, ich habe einen guten Grund, eine bestimmte Sprache zu bevorzugen.Weitere Informationen zu bestimmten Unicode-Zeichensätzen finden Sie im MySQL-Handbuch - http://dev.mysql.com/doc/refman/5.0/en/charset-unicode-sets.html
quelle
utf8_unicode_*
utf8mb4
undutf8mb4_unicode_520_ci
. Diese geben Ihnen den Rest des Chinesischen sowie eine verbesserte Sortierung.Eigentlich möchten Sie wahrscheinlich
utf8_unicode_ci
oder verwendenutf8_general_ci
.utf8_general_ci
sortiert, indem alle Akzente entfernt und sortiert werden, als wäre es ASCIIutf8_unicode_ci
Verwendet die Unicode-Sortierreihenfolge, sodass die Sortierung in mehreren Sprachen korrekt istWenn Sie dies jedoch nur zum Speichern von englischem Text verwenden, sollten sich diese nicht unterscheiden.
quelle
Seien Sie sich dieses Problems sehr, sehr bewusst, das bei der Verwendung auftreten kann
utf8_general_ci
.MySQL unterscheidet einige Zeichen in ausgewählten Anweisungen nicht, wenn die
utf8_general_ci
Sortierung verwendet wird. Dies kann zu sehr bösen Fehlern führen - insbesondere bei Benutzernamen. Abhängig von der Implementierung, die die Datenbanktabellen verwendet, kann dieses Problem böswilligen Benutzern ermöglichen, einen Benutzernamen zu erstellen, der mit einem Administratorkonto übereinstimmt.Dieses Problem tritt zumindest in frühen 5.x-Versionen auf - ich bin mir nicht sicher, ob sich dieses Verhalten später geändert hat.
Ich bin kein DBA, aber um dieses Problem zu vermeiden, gehe ich immer mit
utf8-bin
einem, bei dem die Groß- und Kleinschreibung nicht berücksichtigt wird.Das folgende Skript beschreibt das Problem anhand eines Beispiels.
quelle
'value'
und wären'valUe'
. Der springende Punkt einer Kollatierung ist, dass sie (unter anderem) Regeln bereitstellt, wenn zwei Zeichenfolgen als gleich angesehen werden.Verwenden Sie am besten einen Zeichensatz für
utf8mb4
die Sortierungutf8mb4_unicode_ci
.Der Zeichensatz
utf8
unterstützt nur eine kleine Anzahl von UTF-8-Codepunkten, etwa 6% der möglichen Zeichen.utf8
unterstützt nur das Basic Multilingual Plane (BMP). Es gibt 16 andere Flugzeuge. Jede Ebene enthält 65.536 Zeichen.utf8mb4
unterstützt alle 17 Flugzeuge.MySQL schneidet 4-Byte-UTF-8-Zeichen ab, was zu beschädigten Daten führt.
Der
utf8mb4
Zeichensatz wurde am 24.03.2010 in MySQL 5.5.3 eingeführt.Einige der erforderlichen Änderungen zur Verwendung des neuen Zeichensatzes sind nicht trivial:
ROW_FORMAT=DYNAMIC
HINWEIS: Beim Umschalten auf
Barracuda
vonAntelope
muss der MySQL-Dienst möglicherweise mehrmals neu gestartet werden.innodb_file_format_max
ändert sich erst, nachdem der MySQL-Dienst neu gestartet wurde auf :innodb_file_format = barracuda
.MySQL verwendet das alte
Antelope
InnoDB-Dateiformat.Barracuda
unterstützt dynamische Zeilenformate, die Sie benötigen, wenn Sie die SQL-Fehler zum Erstellen von Indizes und Schlüsseln nach dem Wechsel zum Zeichensatz nicht feststellen möchten:utf8mb4
Das folgende Szenario wurde unter MySQL 5.6.17 getestet: Standardmäßig ist MySQL folgendermaßen konfiguriert:
Beenden Sie Ihren MySQL-Dienst und fügen Sie die Optionen zu Ihrer vorhandenen my.cnf hinzu:
Beispiel einer SQL CREATE-Anweisung:
INDEX contact_idx (contact)
wennROW_FORMAT=DYNAMIC
er aus der CREATE-Anweisung entfernt wurde.HINWEIS: Durch Ändern des Index auf maximal 128 Zeichen
contact
entfällt die Verwendung von Barracuda mitROW_FORMAT=DYNAMIC
Beachten Sie auch: Wenn die Größe des Felds angegeben ist
VARCHAR(128)
, sind dies nicht 128 Byte. Sie können 128, 4-Byte-Zeichen oder 128, 1-Byte-Zeichen verwenden.Diese
INSERT
Anweisung sollte das 4-Byte-Zeichen 'poo' in der 2-Zeile enthalten:Sie können den von der
last
Spalte verwendeten Speicherplatz anzeigen:In Ihrem Datenbankadapter möchten Sie möglicherweise den Zeichensatz und die Sortierung für Ihre Verbindung festlegen:
In PHP wäre dies eingestellt für:
\PDO::MYSQL_ATTR_INIT_COMMAND
Verweise:
quelle
utf8mb4_unicode_520_ci
ist besser. In Zukunft wird esutf8mb4_unicode_800_ci
(oder so etwas) geben, wenn MySQL die Unicode-Standards einholt.Kollatierungen beeinflussen, wie Daten sortiert werden und wie Zeichenfolgen miteinander verglichen werden. Das heißt, Sie sollten die Sortierung verwenden, die die meisten Ihrer Benutzer erwarten.
Beispiel aus der Dokumentation zum Zeichensatz-Unicode :
Also - es hängt von Ihrer erwarteten Benutzerbasis ab und davon, wie viel Sie korrekt sortieren müssen. Für eine englische Benutzerbasis
utf8_general_ci
sollte ausreichen, für andere Sprachen wie Schwedisch wurden spezielle Kollatierungen erstellt.quelle
Im Wesentlichen hängt es davon ab, wie Sie über eine Zeichenfolge denken.
Ich benutze immer utf8_bin wegen des von Guus hervorgehobenen Problems. Meiner Meinung nach ist eine Zeichenfolge in Bezug auf die Datenbank immer noch nur eine Zeichenfolge. Eine Zeichenfolge besteht aus mehreren UTF-8-Zeichen. Ein Zeichen hat eine binäre Darstellung. Warum muss es die Sprache kennen, die Sie verwenden? Normalerweise erstellen Benutzer Datenbanken für Systeme mit dem Umfang für mehrsprachige Websites. Dies ist der springende Punkt bei der Verwendung von UTF-8 als Zeichensatz. Ich bin ein bisschen puristisch, aber ich denke, das Fehlerrisiko überwiegt stark den leichten Vorteil, den Sie bei der Indizierung erhalten können. Alle sprachbezogenen Regeln sollten auf einer viel höheren Ebene als das DBMS durchgeführt werden.
In meinen Büchern sollte "Wert" in einer Million Jahren niemals gleich "Wert" sein.
Wenn ich ein Textfeld speichern und eine Suche ohne Berücksichtigung der Groß- und Kleinschreibung durchführen möchte, verwende ich MYSQL-Zeichenfolgenfunktionen mit PHP-Funktionen wie LOWER () und der PHP-Funktion strtolower ().
quelle
Für UTF-8-Textinformationen sollten Sie verwenden,
utf8_general_ci
weil ...utf8_bin
: Vergleichen Sie Zeichenfolgen mit dem Binärwert jedes Zeichens in der Zeichenfolgeutf8_general_ci
: Vergleichen Sie Zeichenfolgen mit allgemeinen Sprachregeln und mit Vergleichen ohne Berücksichtigung der Groß- und Kleinschreibungaka es wird das Suchen und Indizieren der Daten schneller / effizienter / nützlicher machen.
quelle
Die akzeptierte Antwort schlägt ziemlich definitiv vor, utf8_unicode_ci zu verwenden, und während das für neue Projekte großartig ist, wollte ich meine jüngsten gegenteiligen Erfahrungen nur für den Fall erzählen, dass es jemandem Zeit spart.
Da utf8_general_ci die Standardkollatierung für Unicode in MySQL ist, müssen Sie utf8_unicode_ci an vielen Stellen angeben, wenn Sie utf8_unicode_ci verwenden möchten .
Beispielsweise haben alle Clientverbindungen nicht nur einen Standardzeichensatz (für mich sinnvoll), sondern auch eine Standardkollatierung (dh die Kollatierung wird für Unicode immer standardmäßig utf8_general_ci verwendet).
Wenn Sie utf8_unicode_ci für Ihre Felder verwenden, müssen Ihre Skripts, die eine Verbindung zur Datenbank herstellen, wahrscheinlich aktualisiert werden, um die gewünschte Sortierung explizit zu erwähnen. Andernfalls können Abfragen mit Textzeichenfolgen fehlschlagen, wenn Ihre Verbindung die Standardkollatierung verwendet.
Das Ergebnis ist, dass Sie beim Konvertieren eines vorhandenen Systems beliebiger Größe in Unicode / utf8 möglicherweise gezwungen sind, utf8_general_ci zu verwenden, da MySQL die Standardeinstellungen behandelt.
quelle
Für den von Guus hervorgehobenen Fall würde ich dringend empfehlen, entweder utf8_unicode_cs (Groß- und Kleinschreibung beachten, strikte Übereinstimmung, größtenteils korrekte Reihenfolge) anstelle von utf8_bin (strikte Übereinstimmung, falsche Reihenfolge) zu verwenden.
Wenn das Feld durchsucht werden soll, anstatt für einen Benutzer abgeglichen zu werden, verwenden Sie utf8_general_ci oder utf8_unicode_ci. Bei beiden wird die Groß- und Kleinschreibung nicht berücksichtigt, man wird verlieren ('ß' ist gleich 's' und nicht 'ss'). Es gibt auch sprachspezifische Versionen wie utf8_german_ci, bei denen der Lose Matching besser für die angegebene Sprache geeignet ist.
[Bearbeiten - fast 6 Jahre später]
Ich empfehle den Zeichensatz "utf8" unter MySQL nicht mehr und empfehle stattdessen den Zeichensatz "utf8mb4". Sie stimmen fast vollständig überein, erlauben jedoch ein wenig (viel) mehr Unicode-Zeichen.
Realistisch gesehen hätte MySQL den Zeichensatz "utf8" und die entsprechenden Kollatierungen so aktualisieren müssen, dass sie mit der Spezifikation "utf8" übereinstimmen. Stattdessen sollte ein separater Zeichensatz und entsprechende Kollatierungen die Speicherbezeichnung für diejenigen nicht beeinflussen, die bereits ihren unvollständigen Zeichensatz "utf8" verwenden .
quelle
utf8_unicode_cs
existiert nicht. Die einzige Groß- und Kleinschreibung ist utf8utf8_bin
. Das Problem ist, dass dieutf8_bin
Sortierung falsch ist. Siehe: stackoverflow.com/questions/15218077/…Ich fand diese Kollatierungsdiagramme hilfreich. http://collation-charts.org/mysql60/ . Ich bin mir nicht sicher, welches das verwendete utf8_general_ci ist.
Hier ist zum Beispiel das Diagramm für utf8_swedish_ci. Es zeigt, welche Zeichen als gleich interpretiert werden. http://collation-charts.org/mysql60/mysql604.utf8_swedish_ci.html
quelle
Fügen Sie in Ihrer Datenbank-Upload-Datei vor jeder Zeile die folgende Zeile ein:
Und dein Problem sollte gelöst sein.
quelle
SET NAMES
informiert das direkte Ausgeben einer Abfrage den Client nicht über die Codierung und kann bestimmte Funktionen wie vorbereitete Anweisungen auf sehr subtile Weise beschädigen.