ich habe derzeit mehrere neue Web-Projekte zu erstellen mit einer für mich neuen Herausforderung:
Es soll eine mySQL-Tabelle (5.x) "translate" geben, welche Übersetzungen in die jeweilige Sprache des Users macht. Grundlegender Aufbau der Tabelle:
id|de|en|fr|ru|pl|jp|
Es wird also mittels Smarty und (vermutlich) ADODB folgende Abfragen zur Anzeige des Textes geben: SELECT de FROM translate WHERE id='9291sdfsdf37912379'; SELECT fr FROM translate WHERE id='9291sdfsdf37912379'; SELECT ru FROM translate WHERE id='9291sdfsdf37912379'; SELECT jp FROM translate WHERE id='9291sdfsdf37912379';
.....
Die Spalten sind jeweils mit dem ISO2 der Sprache benannt.
Soweit kein Problem! Jedoch brauche ich einen Grundkurs in Zeichensätzen: - Mit welcher Kollation sollte ich die Tabelle anlegen - Wie die einzelnen Felder? - Was sollte ich in den Meta-Tags im HTML Formular angeben? - Muss ich via SQL-Statement die Kollation der DB evtl. verändern?
Ich habe beispielsweise das Problem mit russisch oder polnisch, dass ich Einträge in den entsprechenden Spalten in phpMyAdmin korrekt angezeigt bekomme, in meiner Webanwendung jedoch entweder kryptische Zeichen oder ?????????? ????????? ????? (ganz viele Fragezeichen) angezeigt werden. Das kann doch nur mit der Verbindung des mySQL Client (also PHP) zur Datenbank zu tun haben, oder? In den Meta-Tags des HTML Dokumentes steht jeweils <meta http-equiv="content-type" content="text/html; charset=utf-8">
Kurzum: Ich bräuchte einen Crash-Kurs, wie Datenbanken und deren Connection zu erstellen sind, wenn man internationale Webseiten mit unterschiedlichen Zeichensätzen darstellen möchte.
Ich bin für jeden Link dankbar! Googeln brachte nur wirre Aussagen und einen Wust an unbrauchbaren Informationen.
Bitte werft mich nicht gleich aus der Group, wenn ich folgendes anbiete, denn es ist mir SEHR wichtig: Wenn sich jemand aus dem Raum Freiburg findet würde ich ein persönliches Gespräch sogar entlohnen und zusätzlich zum Mittagessen einladen (zum Beipiel ins "Paradies" oder eine andere Freiburger Kneipe)
* joerg.rie...@media2u.de wrote: > Jedoch brauche ich einen Grundkurs in Zeichensätzen: > - Mit welcher Kollation sollte ich die Tabelle anlegen > - Wie die einzelnen Felder? > - Was sollte ich in den Meta-Tags im HTML Formular angeben? > - Muss ich via SQL-Statement die Kollation der DB evtl. verändern?
Stelle alles auf UTF8 um, jede relevante Spalte in der Tabelle.
Am Anfang der Verbindung sende das Statement "SET NAMES UTF 8" Dann liefern Anfragen alles als UTF-8 zurück. Du mußt nur noch den ZEichensatz der Webseite auf UTF 8 umstellen. Voilá.
G.
-- BM Computer-Services Schwedenstr. 13 Webdesign 13357 Berlin Internet Tel.: 030/20649400, mobil 0175/7419517 Layout Grafik Web: http://www.bmservices.de Programmierung eMail: kont...@bmservices.de
>> Am Anfang der Verbindung sende das Statement "SET NAMES UTF 8"
> ... und ignoriere geflissentlich den Syntaxfehler ...
Konstruktiver wäre, wenn du meine Nachlässigkeit gleich berichtigt hättest: "SET NAMES 'UTF8'".
G.
-- BM Computer-Services Schwedenstr. 13 Webdesign 13357 Berlin Internet Tel.: 030/20649400, mobil 0175/7419517 Layout Grafik Web: http://www.bmservices.de Programmierung eMail: kont...@bmservices.de
> Warum heißt das eigentlich 'SET NAMES' und nicht z.B. 'SET ENCODING', > was ich intuitiver fände?
,----[ http://dev.mysql.com/doc/refman/5.1/en/charset-connection.html ] | A SET NAMES 'x' statement is equivalent to these three statements: | | SET character_set_client = x; | SET character_set_results = x; | SET character_set_connection = x; `----
Wobei SET NAMES in den meisten Fällen (sofern vorhanden) bessser durch eine treiberspezifische Angabe ersetzt wird. zB bei mysql(i): * mysql_set_charset * mysqli::set_charset / mysqli_set_charset
Karl Pflästerer schrieb: [Warum heißt das eigentlich 'SET NAMES']
> | A SET NAMES 'x' statement is equivalent to these three statements: > | > | SET character_set_client = x; > | SET character_set_results = x; > | SET character_set_connection = x;
Ach so. Wieder was gelernt. Danke!
Gruß, Thomas
-- Ce n'est pas parce qu'ils sont nombreux à avoir tort qu'ils ont raison! (Coluche)
joerg.rie...@media2u.de schrieb am 09.05.2009 in de.comp.lang.php.datenbanken:
> Hallo zusammen, > ich habe derzeit mehrere neue Web-Projekte zu erstellen mit einer für > mich neuen Herausforderung: > Es soll eine mySQL-Tabelle (5.x) "translate" geben, welche > Übersetzungen in die jeweilige Sprache des Users macht. > Grundlegender Aufbau der Tabelle: > id|de|en|fr|ru|pl|jp|
Sicher, dass nie neue Sprachen dazukommen ;-)
Am besten wären hier 3 normalisierte Tabellen, vor allem, wenn jemand das ganze pflegen soll.
_lang_|name|flagge|...
in der die verfügbaren Sprachen definiert sind,
_id_|name|description [1]
in der die Text-IDs definiert sind und eine Verküpfungstabelle
_id_|_lang_|text
in der letztendlich die Texte stehen.
Damit kann z.B. auch - Eine Liste der verfügbaren Sprachen angeboten werden - Eine Übersicht von Text-IDs erstellt werden - geprüft werden, welche IDs noch nicht übersetzt sind etc.
Alles auf UTF-8, dann bist Du auf der sicheren Seite.
Knut
[1] Wenn der Text Platzhalter für z.B. sprintf() enthält, bietet sich an, diese Parameter für den Übersetzer zu erklären. (z.B. ID: "FilesDeleted", Parameter: 1 - Anzahl gelöscht, 2 - Anzahl Dateien gesamt, DE: "Es wurden %1$d Datei(en) von %2$d gelöscht" EN: "%2$d files, %1$d deleted") High-End ist dann, mit unterschiedlichen IDs für Einzahl/Mehrzahl zu arbeiten... _id_|_lang_|_numerus_|text
-- http://es-f.com Web frontend for esniper, the console application for sniping eBay auctions.
> Das kann doch nur mit der Verbindung des mySQL > Client (also PHP) zur Datenbank zu tun haben, oder?
Die Vorposter haben schon recht, es kommt im Prinzip nur auf einheitliche Einstellungen der Datenbank und der zugreifenden Clients an. Ich empfehle an dieser Stelle, entwerder auf dem ganzen DB-Server nur UTF8 zu verwenden und die Parameter in die Serverkonfiguration zu schreiben, oder bei gemischtem Betrieb, die Defaultwerte je Database zu setzen, und dann die Tabellen und Spalten einheitlich neu zu erstellen. Siehe hierzu: http://dev.mysql.com/doc/refman/5.1/de/charset-database.html
Die Nachbarkapitel enthalten ebenfalls viele Infos.
In PHP verwende ich das mysqli Modul und die Objekt-Syntax für MySQL-Verbindungen. Hier ist das umschalten auf UTF ein Klacks.
$MYSQL = new mysqli($SQLHOSTNAME, $SQLUSERNAME, $SQLPASSWORD, $SQLDBNAME);
if (mysqli_connect_errno()) { die('Fehler beim Herstellen der Datenbankverbindung: '.mysqli_connect_error());
}
if (false === $MYSQL->set_charset('utf8')) { die('Fehler beim Setzen des Zeichensatzes für die Datenbankverbindung: '.$MYSQL->error);
}
Hinweis: Die PHP Skripte der Webanwendung sollten ebenfalls in UTF8 abgespeichert werden. Ein entsprechender Editor sollte Verwendung finden.
Wichtig: Bei Zeichenkettenoperationen müssen die multibytesicheren Funktionen Verwendung finden also mb_strlen anstatt strlen.
Je nach PHP Version und Serverkonfiguration müssen die entsprechenden Module geladen sein. Unter Windows z.B. "php_mbstring.dll".
> In den Meta-Tags des HTML Dokumentes steht jeweils > <meta http-equiv="content-type" content="text/html; charset=utf-8">
Ein ausschließliches Setzen des Content-Types im HTML Code ist nicht für alle Browser ausreichend. Am sichersten ist es, wenn auch im HTTP Header der Content-Type angegeben wird. Dies kann entweder durch die Modifikation der Webserverkonfiguration erfolgen, oder in der verwendeten Skriptsprache, z.B. durch
header('content-type: text/html; charset=utf-8');
in PHP bevor sonstige Ausgaben per echo o.ä. erfolgen.
Jetzt sollten die meisten Browser die Seite schon mal richtig darstellen. Das ist aber noch keine Garantie, dass z.B. POST-Daten von Formularen oder GET-Daten aus der URL in UTF8 an die Webanwendung geschickt werden. Der sendende Client ist jederzeit in der Lage hier von UTF8 abzuweichen, und z.B. im lokalen Zeichensatz des Systems zu senden. Wenn ich z.B. in einer reinen UTF8 Seite auf einem deutschen Windows in die Adresszeile klicke und einfach unsinnige Parameter anhänge, dann wird der ganze URL nicht mehr als UTF8 an den Server übermittelt sondern als Windows-1252.
In Formularen, kann der zu sendende Zeichensatz angegeben werden: <form action="index.php" method="post" accept-charset="utf-8"> Die Browser können dies aber theoretisch auch misachten.
Das bedeutet, dass bei der Entgegenahme der Zeichen nochmals auf den Zeichensatz zu prüfen ist und gegebenfalls konvertiert werden muss, bevor die Eingaben nach dem Escaping mit real_escape_string an die Datenbank geschickt werden.
Also irgendwas in dieser Richtung:
$encoding = mb_detect_encoding($nutzereingabe, 'UTF-8,ISO-8859-1', true); if ($encoding == 'ISO-8859-1'){ # Konvertiere ISO-8859-1 nach UTF-8 $nutzereingabe= mb_convert_encoding ($nutzereingabe, 'UTF-8', 'ISO-8859-1');
} elseif ($encoding == 'UTF-8'){
# Encoding OK - Nichts tun
} else {
# Alle anderen Encodings werden derzeit nicht unterstützt die('Nicht unterstütztes Encoding.');
}
Es ist also wichtig, dass eine saubere UTF8-Kette in Eingabe- wie Ausgaberichtung zustande kommt.
Jürgen Schmitts <f4c...@web.de> wrote: > joerg.rie...@media2u.de schrieb:
>> Das kann doch nur mit der Verbindung des mySQL >> Client (also PHP) zur Datenbank zu tun haben, oder?
> Die Vorposter haben schon recht, es kommt im Prinzip nur auf > einheitliche Einstellungen der Datenbank und der zugreifenden Clients > an.
Nein! Details siehe unten.
> Ich empfehle an dieser Stelle, entwerder auf dem ganzen DB-Server > nur UTF8 zu verwenden und die Parameter in die Serverkonfiguration zu > schreiben, oder bei gemischtem Betrieb, die Defaultwerte je Database zu > setzen, und dann die Tabellen und Spalten einheitlich neu zu erstellen.
Schlechter Rat. Details siehe (ganz) unten.
...
> Es ist also wichtig, dass eine saubere UTF8-Kette in Eingabe- wie > Ausgaberichtung zustande kommt.
Nein. "Datenbank intern" gehört jeweils *nicht* in diese Kette.
Mit Version 4.1 hat sich die Zeichensatzunterstützung von MySQL massiv geändert. Während es vorher nur eine globale Einstellung gab, die lediglich für Vergleiche und Sortierung herangezogen wurde (Ein-/Ausgabe und Speicherung erfolgte ohne jedwede Konvertierung) - kann MySQL jetzt für jede Tabellenspalte, für Literale und die Ein-/Ausgabe jeweils getrennte Einstellungen für das Encoding (character set) und Vergleiche/Sortierung (collation) verwenden.
Der absolut wichtigste Punkt dabei: man muß streng unterscheiden zwischen den Einstellungen für die Client/Server-Kommunikation und den Einstellungen für die interne Speicherung. Anders gesagt: wenn der Client mit MySQL erst mal ein Encoding ausgehandelt hat (SET NAMES, character_set_client, character_set_results) dann bekommt er alle Ergebnisse in diesen Encoding, vollkommen unabhängig davon, wie die intern (also z.B. in der Tabelle) gespeichert sind. Ebenfalls muß der Client alle Daten in diesem Encoding anliefern. Falls Konvertierungen notwendig sind, macht der MySQL-Server diese Konvertierungen!
Der häufigste Fehler in diesem Zusammenhang ist, daß einige Clients das falsche Encoding aushandeln (z.B. verwendet der Kommandozeilen-Client defaultmäßig latin1, auch wenn er z.B. aus einem utf8-fähigen xterm aufgerufen wird). Oder daß der Client Daten in gemischtem Encoding anliefert. Z.B. für eine latin1-Spalte in latin1 und für eine utf8-Spalte in utf8.
Bei der Diagnose von Zeichensatzproblemen sollte man ausgiebig Gebrauch machen von der MySQL-Funktion HEX(). Diese wandelt einen String in eine Folge von hexadezimalen Codes um. Man kann dann sehr schnell erkennen, ob das falsch dargestellte "ü" tatsächlich falsch in der Datenbank steht, oder ob es bloß der für den Test verwendete Client falsch darstellt.
So. Noch eine Antwort fehlt. Warum nicht einfach überall utf8 verwenden?
Auf den ersten Blick eine bestechend einfache Lösung. Man spart sich das Denken. Alles paßt in utf8. Und wenn überall utf8 drin ist, muß man auch nirgendwo konvertieren.
Dummerweise ist utf8 teuer. Aus zwei Gründen:
1. in utf8 kann ein Zeichen zwischen 1 und 4 Bytes lang sein (in dem von MySQL unterstützten Teil von Unicode aber nur maximal 3 Bytes). Man nennt das "variable length encoding". Ein solchen Encoding macht alle String-Operationen, die mit Zeichenpositionen arbeiten teuer, weil das Xte Zeichen eben nicht an Position X im String steht. Statt dessen muß man den String von vorn nach hinten durchlaufen und Zeichen- grenzen zählen. Aus O(1) wird O(n).
2. wenn man mit utf8-Strings arbeitet, muß man alle Puffer so dimensionieren, daß sie auch im worst case noch groß genug sind. Also 3 Byte pro Zeichen. Die größeren Puffer erhöhen den Speicherbedarf.
In Verbindung mit MySQL kommt hinzu, daß MySQL einige Limits in Bytes (nicht: Zeichen) hat. Z.B. darf ein Index nicht länger als 1000 Bytes sein oder eine Zeile nicht länger als 64KB. Wenn utf8 im Spiel ist, rechnet MySQL immer pessimistisch. Deswegen gehen z.B. einige Kombinationen mit latin1, aber nicht mit utf8.
Mit utf8 können col1 und col2 jeweils bis zu 600 Bytes lang sein. Für den Index bräuchte man dann 1200 Bytes. MySQL lehnt obiges CREATE Statement dann mit einem Fehler ab.
Deswegen sollte man *immer* vorher nachdenken, welches Zeichen- Repertoire man für eine Tabellenspalte benötigt und dann das kürzeste, noch ausreichende Encoding verwenden. Notfalls kann man das später immer noch aufbohren - und zwar ganz und gar transparent.
Unabhängig davon kann man seine (Web-)Applikation komplett auf utf8 umstellen. Ich würde mittlerweile sogar dazu raten.
On Sun, 28 Jun 2009 15:19:25 +0200 Axel Schwenke wrote:
> Deswegen sollte man *immer* vorher nachdenken, welches Zeichen- > Repertoire man für eine Tabellenspalte benötigt und dann das kürzeste, > noch ausreichende Encoding verwenden. Notfalls kann man das später > immer noch aufbohren - und zwar ganz und gar transparent.
Stimmt schon. In der Praxis hat sich hier dummerweise gezeigt, dass praktisch alle Spalten, die laengere varchars enthalten, auch den kompletten Zeichenvorrat benoetigen _koennten_. ASCII-Zeichenketten treten vorwiegend bei (kurzen) Identifiern auf, und alles andere ist numerisch.
Bei der letzten, groesseren Applikation habe ich gerade einmal eine einzige Spalte gefunden, die ich diesbezueglich einschraenken konnte, das war ein interner Pfad im Dateisystem...
> Schlechter Rat. Details siehe (ganz) unten. ... > Dummerweise ist utf8 teuer. Aus zwei Gründen:
UTF ist teuer in Bezug auf Speicher und Rechenleistung, unbestreitbar. Jedoch ist es nicht unbedingt erforderlich sich im Vorhinein um jede Textspalte zu sorgen. Die meisten Projekte "wachsen" und Performanceprobleme aufgrund von übermäßigem Einsatz von UTF8 in kritischen Spalten lassen sich genauso leicht rückwärts beheben wie sich fehlende UTF8 Unterstützung nachrüsten lässt. Es stellt sich hier dir Frage womit man sich eher rumschlagen möchte. In der Anwendung auftauchende Platzhalter für nicht konvertierbare Zeichen oder irgendwann auftauchende Probleme wenn die Webanwendung die ersten Gigabytes an Daten angehäuft hat und man sich Sorgen macht, wie man die nächsten 5000 Nutzer von der Performance noch reinquetschen soll. Ich favorisiere die Lösung mit UTF8 als Standardwert, da man sonst dazu neigt es zu vergessen wo es doch erforderlich gewesen wäre. Latin1 passt immer komplett in UTF8, andersrum nicht.
>> Es ist also wichtig, dass eine saubere UTF8-Kette in Eingabe- wie >> Ausgaberichtung zustande kommt. ... > Nein. "Datenbank intern" gehört jeweils *nicht* in diese Kette.
Doch gehört sie, ich kann z.B. keine kyrillischen Zeichen in latin1 Spalten speichern, auch wenn der Verbindungszeichensatz auf UTF8 steht. MySQL versucht dann zwar eine Konvertierung, wie schon richtig von Ihnen ausgeführt, kann die Zeichen aber nur durch Platzhalter ersetzen.
> Mit utf8 können col1 und col2 jeweils bis zu 600 Bytes lang sein. > Für den Index bräuchte man dann 1200 Bytes. MySQL lehnt obiges > CREATE Statement dann mit einem Fehler ab.
Macht ja nix, steht im Handbuch unter CREATE INDEX. Ich zitiere:
"Präfixe können bis 1.000 Byte lang sein (767 Byte bei InnoDB-Tabellen). Beachten Sie, dass Präfixbeschränkungen in Byte angegeben werden, wohingegen die Präfixlänge in CREATE INDEX-Anweisungen bei nichtbinären Datentypen (CHAR, VARCHAR, TEXT) als Anzahl der Zeichen interpretiert wird. Dies muss bei der Angabe einer Präfixlänge für eine Spalte berücksichtigt werden, die einen Multibytezeichensatz verwendet."
Frage meinerseits:
Wenn die Indexe mit binärem Vergleich arbeiten, dann sollten Indexe auf Multibyte Spalten zwar zu einer Verkürzung in Bezug auf die Gesamtmenge der im Index erfassten "darstellbaren" Zeichen führen, jedoch auf die eigentliche Performance des Index wenig Auswirkung haben?
> On Sun, 28 Jun 2009 15:19:25 +0200 Axel Schwenke wrote: >> Deswegen sollte man *immer* vorher nachdenken, welches Zeichen- >> Repertoire man für eine Tabellenspalte benötigt und dann das kürzeste, >> noch ausreichende Encoding verwenden. Notfalls kann man das später >> immer noch aufbohren - und zwar ganz und gar transparent.
> Stimmt schon. In der Praxis hat sich hier dummerweise gezeigt, dass > praktisch alle Spalten, die laengere varchars enthalten, auch den > kompletten Zeichenvorrat benoetigen _koennten_. ASCII-Zeichenketten > treten vorwiegend bei (kurzen) Identifiern auf, und alles andere ist > numerisch.
Genau das habe ich auch bei den Ausführungen von Herrn Schwenke gedacht. Die einzigen längeren Textspalten in meinen Projekten die potenziell keine Benutzerweingaben enthalten und mit latin1 auskommen könnten sind meist Spalten für uuids oder Hashes. Selbst bei Usernamen, Kennwörtern oder Pfaden und Dateinamen ist in internationlasierten Anwendungen nicht unbedingt vorauszusetzen, dass hier nur latin1 verwandt wird.
> Bei der letzten, groesseren Applikation habe ich gerade einmal eine > einzige Spalte gefunden, die ich diesbezueglich einschraenken konnte, > das war ein interner Pfad im Dateisystem...
> Servus, > Stefan
Und deshalb macht UTF8 als default Sinn, denn es ist wahrscheinlicher irgendwo mal UTF8 zu vergessen und damit mehr Arbeit zu haben, als es bei einer einzigen Spalte absichtlich wieder herauszunehmen.
=?ISO-8859-1?Q?J=FCrgen_Schmitts?= <f4c...@web.de> wrote: > Axel Schwenke schrieb: >> Schlechter Rat. Details siehe (ganz) unten. > ... >> Dummerweise ist utf8 teuer. Aus zwei Gründen:
> UTF ist teuer in Bezug auf Speicher und Rechenleistung, unbestreitbar. > Jedoch ist es nicht unbedingt erforderlich sich im Vorhinein um jede > Textspalte zu sorgen. Die meisten Projekte "wachsen" und > Performanceprobleme aufgrund von übermäßigem Einsatz von UTF8 in > kritischen Spalten lassen sich genauso leicht rückwärts beheben wie sich > fehlende UTF8 Unterstützung nachrüsten lässt.
Das ist zwar im Prinzip richtig. Trotzdem bin ich ein Anhänger der Lehre "mach es gleich richtig". Wohin man kommt, wenn man es erst schlampig macht und nur bei Problemen mal temporär das Hirn einschaltet, kann man leider viel zu oft sehen.
Es sollte eigentlich immer vorher möglich sein zu enscheiden, welches Zeichenrepertoire man für eine bestimmte Spalte braucht. Und in zweifelhaften Fällen kann man ja das teure UTF8 nehmen.
Woanders macht man das doch auch: du schraubst auch nicht in jede Lampe eine 100W-Birne "wenns zu hell ist, kann ich ja später noch gegen eine kleinere tauschen". Oder leihst dir einen 16-Tonner wenn die Nachbarin fragt, ob du ihr helfen kannst einen Tisch und vier Stühle zu transportieren.
Worum es mir in meinem Posting auch ging: den Leuten klar zu machen, daß UTF8 teuer ist. Erschreckend viele wissen das nicht.
> Ich favorisiere die Lösung mit UTF8 als Standardwert, da man sonst dazu > neigt es zu vergessen wo es doch erforderlich gewesen wäre. Latin1 passt > immer komplett in UTF8, andersrum nicht.
Fein. Ich will auch keinen religiösen Krieg anfangen deswegen. Ich sehe halt nur tatsächlich immer öfter MySQL-Anwender, die genau damit Probleme bekommen. Eine verwandte Unsitte ist, alle VARCHARS immer so lang zu machen, wie nur irgend möglich.
>>> Es ist also wichtig, dass eine saubere UTF8-Kette in Eingabe- wie >>> Ausgaberichtung zustande kommt. > ... >> Nein. "Datenbank intern" gehört jeweils *nicht* in diese Kette.
> Doch gehört sie, ich kann z.B. keine kyrillischen Zeichen in latin1 > Spalten speichern, auch wenn der Verbindungszeichensatz auf UTF8 steht.
Klar. Aber warum solltest du das wollen? Wenn *du* den Zeichenvorrat für eine Spalte einschränkst, dann mußt *du* auch dafür sorgen daß das eingehalten wird. Und wenn die Daten vom Nutzer eingegeben werden, dann mußt du entweder
- auf (z.B.) latin1 einschränken, oder - gleich UTF8 nehmen und dann alles erlauben
>> Mit utf8 können col1 und col2 jeweils bis zu 600 Bytes lang sein. >> Für den Index bräuchte man dann 1200 Bytes. MySQL lehnt obiges >> CREATE Statement dann mit einem Fehler ab.
> Macht ja nix, steht im Handbuch unter CREATE INDEX.
Hahaha.
Im Handbuch stehen viele wichtige Dinge. Aber wer liest das schon? Falls du dich dazu zählst: Herzlichen Glückwunsch! Du bist dann Nummer 2 oder 3 auf meiner persönlichen Liste.
> Frage meinerseits:
> Wenn die Indexe mit binärem Vergleich arbeiten, dann sollten Indexe auf > Multibyte Spalten zwar zu einer Verkürzung in Bezug auf die Gesamtmenge > der im Index erfassten "darstellbaren" Zeichen führen, jedoch auf die > eigentliche Performance des Index wenig Auswirkung haben?
"Verkürzung" im Vergleich wozu?
Für die Performance eines Indexzugriffs sind zwei Dinge wichtig:
1. durchschnittliche Größe eines Index-Eintrags. MySQL hält Indizes in Blöcken und liest immer komplette Blöcke. Je mehr Einträge in einen Block passen, desto weniger (random) IO muß gemacht werden.
MySQL denkt hier mit und komprimiert Indizes. Das geht recht gut, weil die Zeilen im Index ja sortiert sind. Es ist dann recht wahrscheinlich, daß aufeinanderfolgende Zeilen den gleichen Anfang haben.
2. Aufwand für Vergleiche. Collations jenseits von "binary" können richtig heftigen Aufwand bedeuten. Allerdings ist das "nur" CPU-Leistung, und die hat man heute meistens mehr als genug. Im Gegensatz zu I/O-Leistung zumindest.
> =?ISO-8859-1?Q?J=FCrgen_Schmitts?= <f4c...@web.de> wrote: >> Axel Schwenke schrieb: >>> Schlechter Rat. Details siehe (ganz) unten. >> ... >>> Dummerweise ist utf8 teuer. Aus zwei Gründen: >> UTF ist teuer in Bezug auf Speicher und Rechenleistung, unbestreitbar. >> Jedoch ist es nicht unbedingt erforderlich sich im Vorhinein um jede >> Textspalte zu sorgen. Die meisten Projekte "wachsen" und >> Performanceprobleme aufgrund von übermäßigem Einsatz von UTF8 in >> kritischen Spalten lassen sich genauso leicht rückwärts beheben wie sich >> fehlende UTF8 Unterstützung nachrüsten lässt.
> Das ist zwar im Prinzip richtig. Trotzdem bin ich ein Anhänger > der Lehre "mach es gleich richtig". Wohin man kommt, wenn man > es erst schlampig macht und nur bei Problemen mal temporär das > Hirn einschaltet, kann man leider viel zu oft sehen.
> Es sollte eigentlich immer vorher möglich sein zu enscheiden, > welches Zeichenrepertoire man für eine bestimmte Spalte braucht. > Und in zweifelhaften Fällen kann man ja das teure UTF8 nehmen.
> Woanders macht man das doch auch: du schraubst auch nicht in jede > Lampe eine 100W-Birne "wenns zu hell ist, kann ich ja später noch > gegen eine kleinere tauschen". Oder leihst dir einen 16-Tonner > wenn die Nachbarin fragt, ob du ihr helfen kannst einen Tisch > und vier Stühle zu transportieren.
> Worum es mir in meinem Posting auch ging: den Leuten klar zu > machen, daß UTF8 teuer ist. Erschreckend viele wissen das nicht.
>> Ich favorisiere die Lösung mit UTF8 als Standardwert, da man sonst dazu >> neigt es zu vergessen wo es doch erforderlich gewesen wäre. Latin1 passt >> immer komplett in UTF8, andersrum nicht.
> Fein. Ich will auch keinen religiösen Krieg anfangen deswegen. > Ich sehe halt nur tatsächlich immer öfter MySQL-Anwender, die > genau damit Probleme bekommen. Eine verwandte Unsitte ist, alle > VARCHARS immer so lang zu machen, wie nur irgend möglich.
>>>> Es ist also wichtig, dass eine saubere UTF8-Kette in Eingabe- wie >>>> Ausgaberichtung zustande kommt. >> ... >>> Nein. "Datenbank intern" gehört jeweils *nicht* in diese Kette. >> Doch gehört sie, ich kann z.B. keine kyrillischen Zeichen in latin1 >> Spalten speichern, auch wenn der Verbindungszeichensatz auf UTF8 steht.
> Klar. Aber warum solltest du das wollen? Wenn *du* den Zeichenvorrat > für eine Spalte einschränkst, dann mußt *du* auch dafür sorgen daß > das eingehalten wird. Und wenn die Daten vom Nutzer eingegeben werden, > dann mußt du entweder
Da sind wir dann wieder beim Posting von Stefan Fröhlich, der in seier Praxis festgestellt hat, dass bei seinen Textspalten sowieso nur eine dabei war, wo er hätte auf UTF8 verzichten können. In meinen Projekten fallen mir auch nur Uuids oder Hashes ein, wo ich auf UTF8 verzichten könnte, die meisten anderen Spalten enthalten Nutzereingaben und müssen zwangsweise internationalisiert werden.
> - auf (z.B.) latin1 einschränken, oder > - gleich UTF8 nehmen und dann alles erlauben
>>> Mit utf8 können col1 und col2 jeweils bis zu 600 Bytes lang sein. >>> Für den Index bräuchte man dann 1200 Bytes. MySQL lehnt obiges >>> CREATE Statement dann mit einem Fehler ab. >> Macht ja nix, steht im Handbuch unter CREATE INDEX.
> Hahaha.
> Im Handbuch stehen viele wichtige Dinge. Aber wer liest das schon? > Falls du dich dazu zählst: Herzlichen Glückwunsch! Du bist dann > Nummer 2 oder 3 auf meiner persönlichen Liste.
Nicht immer, aber zumindest bei Problemen oder wenn ich mal die Syntaxdetails vergessen habe schaue ich immer ins Handbuch. Ich habe immer eine aktuelle Kopie als chm-Datei auf meinem Entwicklungsrechner. Wenn man's nicht macht bekommt man ja eh immer nur RTFM um die Ohren gehauen.
>> Wenn die Indexe mit binärem Vergleich arbeiten, dann sollten Indexe auf >> Multibyte Spalten zwar zu einer Verkürzung in Bezug auf die Gesamtmenge >> der im Index erfassten "darstellbaren" Zeichen führen, jedoch auf die >> eigentliche Performance des Index wenig Auswirkung haben?
> "Verkürzung" im Vergleich wozu?
> Für die Performance eines Indexzugriffs sind zwei Dinge wichtig:
> 1. durchschnittliche Größe eines Index-Eintrags. MySQL hält Indizes > in Blöcken und liest immer komplette Blöcke. Je mehr Einträge in > einen Block passen, desto weniger (random) IO muß gemacht werden.
> MySQL denkt hier mit und komprimiert Indizes. Das geht recht gut, > weil die Zeilen im Index ja sortiert sind. Es ist dann recht > wahrscheinlich, daß aufeinanderfolgende Zeilen den gleichen > Anfang haben.
> 2. Aufwand für Vergleiche. Collations jenseits von "binary" können > richtig heftigen Aufwand bedeuten. Allerdings ist das "nur" > CPU-Leistung, und die hat man heute meistens mehr als genug. > Im Gegensatz zu I/O-Leistung zumindest.
> XL
Dann ist es schon in etwas so, wie ich es mir gedacht habe. UTF8 für Indexe erzeugt etwas mehr Random IO, da in der gleichen Anzahl von Bytes weniger Unterschiede abgebildet werden können wenn Multibytezeichen darin vorkommen. Ansonsten ist es Jacke wie Hose.
> Im Handbuch stehen viele wichtige Dinge. Aber wer liest das schon? > Falls du dich dazu zählst: Herzlichen Glückwunsch! Du bist dann > Nummer 2 oder 3 auf meiner persönlichen Liste.
Nimmst Du mich bitte als Nummer 4 ebenfalls mit auf?
Ich lese _immer_ erst im Handbuch, wenn ich ein Problem habe und es alleine nicht gelöst bekomme, oder wenn ich etwas Bestimmtes such. Erst wenn ich dort nichts finde oder mit dem gefundenen nicht klar komme, frage ich woanders.
Ja. Meine Kombo aus Knews und fte kann nicht wirklich gut mit non-latin1. Aber ich bin nun mal daran gewöhnt.
>> Im Handbuch stehen viele wichtige Dinge. Aber wer liest das schon? >> Falls du dich dazu zählst: Herzlichen Glückwunsch! Du bist dann >> Nummer 2 oder 3 auf meiner persönlichen Liste.
> Nimmst Du mich bitte als Nummer 4 ebenfalls mit auf?