Mir ist klar, dass CHAR empfohlen wird, wenn alle meine Werte eine feste Breite haben. Na und? Wählen Sie aus Sicherheitsgründen einfach VARCHAR für alle Textfelder.
Mir ist klar, dass CHAR empfohlen wird, wenn alle meine Werte eine feste Breite haben. Na und? Wählen Sie aus Sicherheitsgründen einfach VARCHAR für alle Textfelder.
Antworten:
Wählen Sie im Allgemeinen CHAR, wenn alle Zeilen nahezu dieselbe Länge haben . Wählen Sie VARCHAR, wenn die Länge erheblich variiert . CHAR kann auch etwas schneller sein, da alle Zeilen gleich lang sind.
Es variiert je nach DB-Implementierung, aber im Allgemeinen verwendet VARCHAR zusätzlich zu den tatsächlichen Daten ein oder zwei weitere Speicherbytes (für Länge oder Beendigung). Speichern Sie also (vorausgesetzt, Sie verwenden einen 1-Byte-Zeichensatz) das Wort "FooBar".
Unter dem Strich kann CHAR für Daten relativ gleicher Länge (innerhalb eines Längenunterschieds von zwei Zeichen) schneller und platzsparender sein .
Hinweis : Microsoft SQL hat 2 Byte Overhead für eine VARCHAR. Dies kann von DB zu DB variieren, aber im Allgemeinen ist mindestens 1 Byte Overhead erforderlich, um die Länge oder EOL auf einem VARCHAR anzuzeigen.
Wie Gaven in den Kommentaren hervorhob, speichert CHAR die maximale Anzahl von Bytes, die zum Speichern der Anzahl von Zeichen erforderlich sind, wenn Sie einen Mehrbyte-Zeichensatz mit variabler Länge wie UTF8 verwenden. Wenn UTF8 also höchstens 3 Bytes zum Speichern eines Zeichens benötigt, wird CHAR (6) auf 18 Bytes festgelegt, selbst wenn nur lateinische 1 Zeichen gespeichert werden. In diesem Fall wird VARCHAR eine viel bessere Wahl.
Wenn Sie mit mir und mit Oracle arbeiten, würde ich Sie wahrscheinlich dazu bringen, sie unter varchar
fast allen Umständen zu verwenden. Die Annahme, dass char
weniger Rechenleistung verbraucht, als varchar
wahr sein mag ... für den Moment ... aber Datenbank-Engines werden mit der Zeit besser und diese Art von allgemeiner Regel hat die Entstehung eines zukünftigen "Mythos".
Eine andere Sache: Ich habe noch nie ein Leistungsproblem gesehen, weil sich jemand dafür entschieden hat varchar
. Sie werden Ihre Zeit viel besser nutzen, um guten Code (weniger Aufrufe der Datenbank) und effizientes SQL (wie funktionieren Indizes, wie trifft der Optimierer Entscheidungen, warum ist exists
schneller als in
gewöhnlich ...) zu schreiben .
Letzter Gedanke: Ich habe alle möglichen Probleme bei der Verwendung von gesehen CHAR
, Menschen, die nach "suchen, wann sie suchen sollten", oder Menschen, die nach "FOO" suchen, wenn sie nach "FOO" suchen sollten (eine Reihe von Räumen hier). oder Personen, die die nachfolgenden Leerzeichen nicht kürzen, oder Fehler, bei denen Powerbuilder dem von einer Oracle-Prozedur zurückgegebenen Wert bis zu 2000 Leerzeichen hinzufügt.
Neben Leistungsvorteilen, CHAR
kann verwendet werden , um anzuzeigen , dass alle Werte sollen gleich lang sein, beispielsweise eine Spalte für US - Bundesstaat Abkürzungen.
CHAR
, müssen Sie sicherstellen, dass Ihre Constraint-Rabatte aufgefüllt werden.
Char ist etwas schneller. Wenn Sie also eine Spalte haben, von der Sie wissen, dass sie eine bestimmte Länge hat, verwenden Sie char. Beispiel: Speichern von (M) Ale / (F) Emale / (U) Unbekannt für das Geschlecht oder 2 Zeichen für einen US-Bundesstaat.
Ist NChar oder Char besser als ihre var-Alternativen?
Gute Frage. Die einfache Antwort lautet in bestimmten Situationen Ja. Mal sehen, ob das erklärt werden kann.
Natürlich wissen wir alle, dass die Tabelle viel kleiner ist, wenn ich eine Tabelle mit einer Spalte von varchar (255) erstelle (nennen wir diese Spalte myColumn) und eine Million Zeilen einfüge, aber für jede Zeile nur wenige Zeichen in myColumn einfüge Anzahl der von der Speicher-Engine benötigten Datenseiten), als wenn ich myColumn als char (255) erstellt hätte. Jedes Mal, wenn ich eine Operation (DML) für diese Tabelle ausführe und viele Zeilen anfordere, ist es schneller, wenn myColumn varchar ist, da ich mich am Ende nicht um all diese "zusätzlichen" Leerzeichen bewegen muss . Verschieben, z. B. wenn SQL Server interne Sortierungen ausführt, z. B. während eines bestimmten Vorgangs oder einer Vereinigung, oder wenn während des Abfrageplans eine Zusammenführung ausgewählt wird usw.
Die Verwendung von Varchar ist jedoch mit einem gewissen Aufwand verbunden. SQL Server muss einen Zwei-Byte-Indikator (Overhead) verwenden, um in jeder Zeile zu ermitteln, wie viele Bytes die myColumn dieser bestimmten Zeile enthält. Es sind nicht die zusätzlichen 2 Bytes, die das Problem darstellen, sondern die Notwendigkeit, die Länge der Daten in myColumn in jeder Zeile zu "dekodieren".
Nach meinen Erfahrungen ist es am sinnvollsten, char anstelle von varchar für Spalten zu verwenden, die in Abfragen verknüpft werden. Zum Beispiel der Primärschlüssel einer Tabelle oder eine andere Spalte, die indiziert wird. CustomerNumber in einer demografischen Tabelle oder CodeID in einer Decodiertabelle oder OrderNumber in einer Auftragstabelle. Durch die Verwendung von char kann die Abfrage-Engine den Join schneller ausführen, da sie (deterministisch) gerade Zeigerarithmetik ausführen kann, anstatt ihre Zeiger beim Lesen der Seiten um eine variable Anzahl von Bytes verschieben zu müssen. Ich weiß, dass ich dich in diesem letzten Satz verloren haben könnte. Joins in SQL Server basieren auf der Idee von "Prädikaten". Ein Prädikat ist eine Bedingung. Zum Beispiel myColumn = 1 oder OrderNumber <500.
Wenn SQL Server eine DML-Anweisung ausführt und die Prädikate oder "Schlüssel", die verknüpft werden, eine feste Länge (char) haben, muss die Abfrage-Engine nicht so viel Arbeit leisten, um Zeilen von einer Tabelle zu Zeilen von abzugleichen ein anderer Tisch. Es muss nicht herausfinden, wie lange sich die Daten in der Zeile befinden, und dann die Zeichenfolge entlang gehen, um das Ende zu finden. Das alles braucht Zeit.
Denken Sie jetzt daran, dass dies leicht schlecht implementiert werden kann. Ich habe gesehen, dass Zeichen für Primärschlüsselfelder in Online-Systemen verwendet werden. Die Breite muss klein gehalten werden, dh char (15) oder etwas Vernünftiges. Und es funktioniert am besten in Online-Systemen, da Sie normalerweise nur eine kleine Anzahl von Zeilen abrufen oder auf den Kopf stellen. Daher ist es eine triviale Aufgabe, die nachfolgenden Leerzeichen in der Ergebnismenge zu "kürzen", anstatt Millionen von Zeilen beizutreten Zeilen von einer Tabelle zu Millionen von Zeilen in einer anderen Tabelle.
Ein weiterer Grund, warum CHAR auf Online-Systemen gegenüber varchar sinnvoll ist, besteht darin, dass Seitenaufteilungen reduziert werden. Wenn Sie char verwenden, "reservieren" (und verschwenden) Sie im Wesentlichen diesen Speicherplatz. Wenn also ein Benutzer später vorbeikommt und mehr Daten in diese Spalte einfügt, hat SQL bereits Speicherplatz dafür zugewiesen und es geht.
Ein weiterer Grund für die Verwendung von CHAR ähnelt dem zweiten Grund. Wenn ein Programmierer oder Benutzer ein "Batch" -Update für Millionen von Zeilen durchführt und beispielsweise einem Notizfeld einen Satz hinzufügt, erhalten Sie mitten in der Nacht keinen Anruf von Ihrem DBA und fragen sich, warum die Laufwerke voll sind. Mit anderen Worten, dies führt zu einem vorhersehbareren Wachstum der Größe einer Datenbank.
Das sind also drei Möglichkeiten, wie ein Online-System (OLTP) von char over varchar profitieren kann. Ich verwende char in einem Warehouse- / Analyse- / OLAP-Szenario kaum, da Sie normalerweise so viele Daten haben, dass all diese char-Spalten zu viel verschwendetem Speicherplatz führen können.
Denken Sie daran, dass char Ihre Datenbank viel größer machen kann, aber die meisten Backup-Tools verfügen über Datenkomprimierung, sodass Ihre Backups in der Regel ungefähr so groß sind, als hätten Sie varchar verwendet. Zum Beispiel LiteSpeed oder RedGate SQL Backup.
Eine andere Verwendung sind Ansichten, die zum Exportieren von Daten in eine Datei mit fester Breite erstellt wurden. Angenommen, ich muss einige Daten in eine flache Datei exportieren, um sie von einem Mainframe lesen zu können. Es ist eine feste Breite (nicht begrenzt). Ich möchte die Daten in meiner "Staging" -Tabelle als varchar speichern (wodurch weniger Speicherplatz in meiner Datenbank verbraucht wird) und dann eine Ansicht verwenden, um alles auf das char-Äquivalent zu CAST, wobei die Länge der Breite der festen Breite für diese Spalte entspricht . Zum Beispiel:
create table tblStagingTable (
pkID BIGINT (IDENTITY,1,1),
CustomerFirstName varchar(30),
CustomerLastName varchar(30),
CustomerCityStateZip varchar(100),
CustomerCurrentBalance money )
insert into tblStagingTable
(CustomerFirstName,CustomerLastName, CustomerCityStateZip) ('Joe','Blow','123 Main St Washington, MD 12345', 123.45)
create view vwStagingTable AS
SELECT CustomerFirstName = CAST(CustomerFirstName as CHAR(30)),
CustomerLastName = CAST(CustomerLastName as CHAR(30)),
CustomerCityStateZip = CAST(CustomerCityStateZip as CHAR(100)),
CustomerCurrentBalance = CAST(CAST(CustomerCurrentBalance as NUMERIC(9,2)) AS CHAR(10))
SELECT * from vwStagingTable
Das ist cool, weil meine Daten intern weniger Speicherplatz beanspruchen, weil sie varchar verwenden. Wenn ich jedoch DTS oder SSIS oder nur ein Ausschneiden und Einfügen von SSMS in Notepad verwende, kann ich die Ansicht verwenden und die richtige Anzahl nachfolgender Leerzeichen abrufen. In DTS hatten wir früher eine Funktion namens "Verdammt, ich vergesse, ich glaube, sie wurde" Spalten vorschlagen "oder so genannt. In SSIS können Sie das nicht mehr tun, Sie müssen den Flat File Connection Manager mühsam definieren. Da Sie jedoch Ihre Ansicht eingerichtet haben, kann SSIS die Breite jeder Spalte kennen und beim Erstellen Ihrer Datenflussaufgaben viel Zeit sparen.
Unterm Strich also ... benutze varchar. Es gibt nur sehr wenige Gründe, char zu verwenden, und dies nur aus Leistungsgründen. Wenn Sie ein System mit Hunderten von Millionen von Zeilen haben, werden Sie einen merklichen Unterschied feststellen, wenn die Prädikate deterministisch (char) sind, aber für die meisten Systeme, die char verwenden, wird einfach Platz verschwendet.
Hoffentlich hilft das. Jeff
Es gibt Leistungsvorteile, aber hier ist einer, der nicht erwähnt wurde: Zeilenmigration. Mit char reservieren Sie den gesamten Speicherplatz im Voraus. Nehmen wir also an, Sie haben einen char (1000) und speichern 10 Zeichen. Sie verbrauchen alle 1000 Zeichen des Speicherplatzes. In einem varchar2 (1000) werden nur 10 Zeichen verwendet. Das Problem tritt auf, wenn Sie die Daten ändern. Angenommen, Sie aktualisieren die Spalte so, dass sie jetzt 900 Zeichen enthält. Möglicherweise ist der Speicherplatz zum Erweitern des Varchars im aktuellen Block nicht verfügbar. In diesem Fall muss die DB-Engine die Zeile in einen anderen Block migrieren und im ursprünglichen Block einen Zeiger auf die neue Zeile im neuen Block setzen. Um diese Daten zu lesen, muss die DB-Engine nun 2 Blöcke lesen.
Niemand kann eindeutig sagen, dass Varchar oder Char besser sind. Es gibt einen Raum für einen zeitlichen Kompromiss und die Überlegung, ob die Daten aktualisiert werden, insbesondere wenn eine gute Chance besteht, dass sie wachsen.
Es gibt einen Unterschied zwischen einer frühen Leistungsoptimierung und der Verwendung einer Best-Practice-Regel. Wenn Sie neue Tabellen erstellen, in denen Sie immer ein Feld mit fester Länge haben, ist es sinnvoll, CHAR zu verwenden. In diesem Fall sollten Sie es verwenden. Dies ist keine frühe Optimierung, sondern die Implementierung einer Faustregel (oder einer bewährten Methode).
dh - Wenn Sie ein 2-Buchstaben-Statusfeld haben, verwenden Sie CHAR (2). Wenn Sie ein Feld mit den tatsächlichen Statusnamen haben, verwenden Sie VARCHAR.
Ich würde varchar wählen, es sei denn, die Spalte speichert einen festen Wert wie den US-Statuscode - der immer 2 Zeichen lang ist und die Liste der gültigen US-Statuscodes ändert sich nicht oft :).
In jedem anderen Fall würde ich varchar wählen, selbst wenn ich ein Hash-Passwort speichere (das eine feste Länge hat).
Why - char-Typ Spalte wird immer mit Leerzeichen erfüllt, wodurch die Spalte my_column als char (5) mit dem Wert 'ABC' im Vergleich definiert wird:
my_column = 'ABC' -- my_column stores 'ABC ' value which is different then 'ABC'
falsch.
Diese Funktion kann während der Entwicklung zu vielen irritierenden Fehlern führen und das Testen erschweren.
CHAR belegt weniger Speicherplatz als VARCHAR, wenn alle Datenwerte in diesem Feld gleich lang sind. Vielleicht ist eine 800-GB-Datenbank im Jahr 2009 in jeder Hinsicht dieselbe wie eine 810-GB-Datenbank, wenn Sie die VARCHARs in CHARs konvertiert haben, aber für kurze Zeichenfolgen (1 oder 2 Zeichen) ist CHAR immer noch eine branchenweit bewährte Methode.
Wenn Sie sich nun die Vielzahl der Datentypen ansehen, die die meisten Datenbanken auch nur für Ganzzahlen (Bit, Winzig, Int, Bigint) bereitstellen, gibt es Gründe, einen über den anderen zu wählen. Einfach jedes Mal Bigint zu wählen, ist eigentlich ein bisschen unwissend über die Zwecke und Verwendungen des Feldes. Wenn ein Feld einfach das Alter einer Person in Jahren darstellt, ist ein Bigint übertrieben. Jetzt ist es nicht unbedingt "falsch", aber es ist nicht effizient.
Aber es ist ein interessantes Argument, und da sich die Datenbanken im Laufe der Zeit verbessern, könnte argumentiert werden, dass CHAR vs VARCHAR weniger relevant werden.
Ich stehe zu Jim McKeeths Kommentar.
Indizierung und vollständige Tabellenscans sind außerdem schneller, wenn Ihre Tabelle nur CHAR-Spalten enthält. Grundsätzlich kann der Optimierer vorhersagen, wie groß jeder Datensatz ist, wenn er nur CHAR-Spalten enthält, während er den Größenwert jeder VARCHAR-Spalte überprüfen muss.
Wenn Sie eine VARCHAR-Spalte auf eine Größe aktualisieren, die größer als der vorherige Inhalt ist, können Sie außerdem die Datenbank zwingen, ihre Indizes neu zu erstellen (da Sie die Datenbank gezwungen haben, den Datensatz physisch auf die Festplatte zu verschieben). Bei CHAR-Spalten wird das nie passieren.
Aber Sie werden sich wahrscheinlich nicht um den Leistungseinbruch kümmern, es sei denn, Ihr Tisch ist riesig.
Erinnere dich an Djikstras weise Worte. Frühe Leistungsoptimierung ist die Wurzel allen Übels.
CHAR
Spalte aktualisieren, müssen auch die Indizes aktualisiert werden. Diesbezüglich besteht kein Unterschied beim Aktualisieren einer VARCHAR- oder CHAR-Spalte. Denken Sie an ein Update FOO
auf BAR
.
Viele Leute haben darauf hingewiesen, dass die Verwendung von CHAR einige Vorteile hat, wenn Sie die genaue Länge des Werts kennen. Aber während es heute großartig ist, US-Bundesstaaten als CHAR (2) zu speichern, befinden Sie sich in einer Welt voller Schmerzen, wenn Sie die Nachricht vom Verkauf erhalten, dass wir gerade unseren ersten Verkauf nach Australien getätigt haben. Ich sende immer, um zu überschätzen, wie lange Felder meiner Meinung nach dauern müssen, anstatt eine „genaue“ Vermutung anzustellen, um zukünftige Ereignisse abzudecken. VARCHAR gibt mir mehr Flexibilität in diesem Bereich.
Ich denke, in Ihrem Fall gibt es wahrscheinlich keinen Grund, sich nicht für Varchar zu entscheiden. Es gibt Ihnen Flexibilität und wie bereits von einer Reihe von Befragten erwähnt, ist die Leistung jetzt so, dass wir Sterblichen (im Gegensatz zu Google DBAs) den Unterschied nicht bemerken, außer unter ganz bestimmten Umständen.
Eine interessante Sache, die es zu beachten gilt, wenn es um DB-Typen geht, ist, dass SQLite (eine beliebte Minidatenbank mit ziemlich beeindruckender Leistung) alles als Zeichenfolge und Typen im laufenden Betrieb in die Datenbank einfügt.
Ich benutze immer VarChar und mache es normalerweise viel größer, als ich dringend brauche. Z.B. 50 für Vorname, wie Sie sagen, warum nicht nur um sicher zu gehen.
Ich würde NIEMALS Zeichen verwenden. Ich habe diese Debatte mit vielen Menschen geführt und sie sprechen immer das müde Klischee an, dass Char schneller ist. Nun, ich sage, wie viel schneller? Worüber reden wir hier, Millisekunden, Sekunden und wenn ja, wie viele? Sie sagen mir, weil jemand behauptet, es sei ein paar Millisekunden schneller, sollten wir Tonnen von schwer zu behebenden Fehlern in das System einführen?
Hier sind einige Probleme, auf die Sie stoßen werden:
Jedes Feld wird aufgefüllt, sodass Sie für immer Code erhalten, der überall RTRIMS enthält. Dies ist auch eine enorme Speicherplatzverschwendung für die längeren Felder.
Angenommen, Sie haben das fundamentale Beispiel für ein Zeichenfeld mit nur einem Zeichen, aber das Feld ist optional. Wenn jemand eine leere Zeichenfolge an dieses Feld übergibt, wird es zu einem Leerzeichen. Wenn eine andere Anwendung / ein anderer Prozess dies abfragt, erhalten sie einen einzelnen Speicherplatz, wenn sie rtrim nicht verwenden. Wir hatten XML-Dokumente, -Dateien und andere Programme, die nur ein Leerzeichen in optionalen Feldern anzeigen und Dinge beschädigen.
Jetzt müssen Sie sicherstellen, dass Sie Nullen und keine leere Zeichenfolge an das Feld char übergeben. Aber das ist NICHT die richtige Verwendung von null. Hier ist die Verwendung von null. Nehmen wir an, Sie erhalten eine Datei von einem Anbieter
Name | Geschlecht | Stadt
Bob || Los Angeles
Wenn das Geschlecht nicht angegeben ist, geben Sie Bob, die leere Zeichenfolge und Los Angeles in die Tabelle ein. Nehmen wir nun an, Sie erhalten die Datei und ihre Formatänderungen. Das Geschlecht ist nicht mehr enthalten, war aber in der Vergangenheit.
Name | Stadt
Bob | Seattle
Nun, da das Geschlecht nicht enthalten ist, würde ich null verwenden. Varchars unterstützen dies ohne Probleme.
Char dagegen ist anders. Sie müssen immer null senden. Wenn Sie jemals eine leere Zeichenfolge senden, wird ein Feld mit Leerzeichen angezeigt.
Ich konnte mit all den Fehlern, die ich durch Zeichen und in ungefähr 20 Jahren Entwicklung beheben musste, weitermachen.
Die Berechnung der tatsächlich benötigten Größe für einen Spaltenwert und die Zuweisung des Speicherplatzes für einen Varchar ist mit einem geringen Verarbeitungsaufwand verbunden. Wenn Sie also sicher sind, wie lange der Wert immer sein wird, ist es besser, Char zu verwenden und den Treffer zu vermeiden.
Es ist der klassische Kompromiss zwischen Raum und Leistung.
In MS SQL 2005 hat Varchar (oder NVarchar für Sprachen, für die zwei Bytes pro Zeichen erforderlich sind, dh Chinesisch) eine variable Länge. Wenn Sie der Zeile hinzufügen, nachdem sie auf die Festplatte geschrieben wurde, werden die Daten an einem nicht zusammenhängenden Speicherort der ursprünglichen Zeile lokalisiert und führen zu einer Fragmentierung Ihrer Datendateien. Dies beeinträchtigt die Leistung.
Wenn der Speicherplatz kein Problem darstellt, ist Char für die Leistung besser geeignet. Wenn Sie jedoch die Datenbankgröße niedrig halten möchten, sind Varchars besser.
Zersplitterung. Char reserviert Platz und VarChar nicht. Für die Aktualisierung von varchar kann eine Seitenteilung erforderlich sein.
CHAR
Spalte zu einer Seitenaufteilung kommen .
In einigen SQL-Datenbanken wird VARCHAR auf seine maximale Größe aufgefüllt, um die Offsets zu optimieren. Dies dient zur Beschleunigung vollständiger Tabellenscans und Indizes.
Aus diesem Grund sparen Sie mit einem VARCHAR (200) im Vergleich zu einem CHAR (200) keinen Platz.
Die Verwendung von CHAR (NCHAR) und VARCHAR (NVARCHAR) führt zu Unterschieden in der Art und Weise, wie der Datenbankserver die Daten speichert. Der erste führt nachgestellte Leerzeichen ein; Bei der Verwendung mit dem LIKE-Operator in SQL SERVER-Funktionen ist ein Problem aufgetreten. Ich muss es also sicher machen, indem ich ständig VARCHAR (NVARCHAR) verwende.
Wenn wir beispielsweise eine Tabelle TEST (ID INT, Status CHAR (1)) haben und Sie eine Funktion schreiben, um alle Datensätze mit einem bestimmten Wert wie dem folgenden aufzulisten:
CREATE FUNCTION List(@Status AS CHAR(1) = '')
RETURNS TABLE
AS
RETURN
SELECT * FROM TEST
WHERE Status LIKE '%' + @Status '%'
In dieser Funktion erwarten wir, dass die Funktion beim Setzen des Standardparameters alle Zeilen zurückgibt, dies jedoch nicht. Wenn Sie den Datentyp @Status in VARCHAR ändern, wird das Problem behoben.