Was sind die Anwendungsfälle für die Auswahl von CHAR über VARCHAR in SQL?


270

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:


386

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".

  • CHAR (6) = 6 Bytes (kein Overhead)
  • VARCHAR (10) = 8 Bytes (2 Bytes Overhead)
  • CHAR (10) = 10 Bytes (4 Bytes Overhead)

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.


20
Ein weiterer Grund ist die Aufteilung und Fragmentierung von Seiten. Ich hatte eine Tabelle mit einer IDEN-PK, die aufgrund von Seitenteilungen in Varchar-Spalten zu 99% fragmentiert war. Eine sehr aktive Tabelle und von Natur aus der Anwendung eine neue Zeile leere Zeile erstellt und dann gefüllt. Char hat das Fragmentierungsproblem behoben.
Paparazzo

12
@ Jim McKeeth - Diese Berechnungen sind nur wahr, wenn Sie den Zeichensatz latin1 verwenden. Da die meisten Benutzer heutzutage utf8 verwenden sollten, verwenden Ihre CHAR-Spalten im Durchschnitt das Dreifache des Speicherplatzes als VARCHAR, in dem hauptsächlich Zeichen in der mehrsprachigen Basisebene gespeichert sind.
Gavin Towey

11
@ JimMcKeeth ja, das ist genau richtig. Da CHAR eine feste Länge hat, muss es daher auf den maximal möglichen Platz festgelegt werden, der verwendet werden kann. In UTF8 sind das 3 Bytes pro Zeichen. Für varchar ist es kostenlos, je nach Bedarf 1-3 Bytes pro Zeichen zu verwenden. Dies ist im MySQL-Handbuch: dev.mysql.com/doc/refman/5.0/en/charset-unicode-utf8.html
Gavin Towey

3
Was ist der Unterschied zwischen der Zeichenfolge FooBar und varchar (100) und char (100)? Ich denke, das zeigt den Unterschied besser, ja? Nein?
Nenotlep

4
@GavinTowey SQLSERVER verwendet UCS-2 für seine NCHAR- und NVARCHAR-Datentypen. Es sind immer zwei Bytes pro Zeichen.
1010

69

Wenn Sie mit mir und mit Oracle arbeiten, würde ich Sie wahrscheinlich dazu bringen, sie unter varcharfast allen Umständen zu verwenden. Die Annahme, dass charweniger Rechenleistung verbraucht, als varcharwahr 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 existsschneller als ingewö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.


20
Ich bin mit Ihrem ersten Absatz nicht einverstanden, da char möglicherweise einen Hinweis liefert, der für Optimierer, auch für zukünftige, nützlich sein kann, und es kann hilfreich sein, die Absicht der Spalte zu kommunizieren. Aber +1 für Ihren dritten Absatz. Ich hasse all die zusätzlichen Räume. Ein Feld sollte einfach alles speichern, was ich hineingesteckt habe, ohne all die [erklärenden] Auffüllungen. Grundsätzlich verwende ich char nur, wenn alle Daten genau gleich lang sein sollen, nicht mehr und nicht weniger, jetzt und für immer. Dies ist natürlich sehr selten und normalerweise ein Zeichen (1).
Jeffrey L Whitledge

char bietet auch einen Hinweis für Analysten und Entwickler ... dieses Ding ist x Anzahl von Zeichen .... Wenn sie daran denken, es in einem anderen Format zu serialisieren, könnte dies hilfreich sein. (Ich war gezwungen, eine md5-Prüfsumme in einem Zeichen in mssql zu speichern, das keinen UUID-Typ hatte ... und ich wollte nie etwas <32 Bytes ... auch eine Einschränkung für die Spalte).
Joe vom

31

Neben Leistungsvorteilen, CHARkann verwendet werden , um anzuzeigen , dass alle Werte sollen gleich lang sein, beispielsweise eine Spalte für US - Bundesstaat Abkürzungen.


Oder Ländercodes - können helfen, zwischen der Verwendung einer 2- oder 3-stelligen Ländercode-Abkürzung zu unterscheiden
Dan Field

Wenn es sich wirklich um eine feste Länge handelt, sollte es eine Einschränkung geben, die dies erzwingt. Wenn Sie jedoch verwenden CHAR, müssen Sie sicherstellen, dass Ihre Constraint-Rabatte aufgefüllt werden.
jpmc26

18

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.


4
Ich bin mir nicht sicher, ob dies eine großartige Antwort ist, da eine ENUM normalerweise viel sinnvoller ist, obwohl ich nicht sicher bin, wie weit verbreitet dieser Typ ist (außerhalb von MySQL).
Bobby Jack

Mir scheint, dass die Menge der Zustände nicht unbedingt unveränderlich ist, daher scheint char (2) viel angemessener als eine Aufzählung.
Kearns

1
@Bobby Jack - Ich kenne die spezifischen Details einer bestimmten SQL-Enum-Implementierung nicht, denke jedoch daran, dass eine als 4-Byte-Ganzzahl gespeicherte Enum möglicherweise mehr Speicherplatz benötigt als eine char (1) - oder char (2) -Spalte mit der gleiche Daten. In gewisser Weise sind Aufzählungen in Bezug auf ihre Interpretation logischer, und das mag zwingend sein, aber alles in einem RDBMS-System ist auf einer bestimmten Ebene abstrakt und unterliegt den für die Tabellen definierten Prädikaten.
Jeffrey L Whitledge

4
Schlechtes Beispiel, ENUM ist am besten für diesen Fall. Besseres Beispiel wäre ein 3-Buchstaben-IATA-Flughafencode
Andrew G. Johnson

5
@ Andrew, nicht alle DBs unterstützen ENUM-Datentypen. MSSQLServer zum Beispiel nicht. Außerdem benötigt eine als int gespeicherte ENUM 4 Bytes. CHAR (1) benötigt 1 Byte und NCHAR (1) 2 Byte.
Jarrett Meyer

17

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


Sie sagen, fester Chat nimmt nicht nur beim Speichern mehr Platz ein, sondern auch beim Transportieren oder "Bewegen", wie Sie sagen? Zum Beispiel von DB Server zu meinem Client? Wann verlieren wir diese Null-Bytes?
Die rote Erbse

9

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.


Ich denke, Sie haben einen Tippfehler in Ihrem Beitrag - sollte varchar2 (1000) nicht CHAR (1000) sein?
Matt Rogish

8

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.


8

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.


1
Zumindest in MSSQL Server ist 'abc' = 'abc'. Ich habe nie ganz herausgefunden, ob ich diese Funktion mag oder verabscheue ...
Mark Brackett

Eine gute Lektüre über das Auffüllen von Saibling hier Auffüllen
Edward

6

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.


4

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.


4
In Ihrem Kommentar gibt es ein gewisses Maß an Spekulation. Ich habe immer wieder gesehen, dass Annahmen wie diese getestet werden und sich das genaue Gegenteil herausstellt. Das Problem ist, dass viele Ingenieure solche Informationen als Evangelium betrachten. Bitte Leute, erstellen Sie Testfälle, die Ihre realen Situationen widerspiegeln.
Ethan Post

Ethan ist völlig richtig. Dies hängt also von der Implementierung ab, die Sie verwenden, und ist ohne Verweise auf die tatsächliche (Produkt, Version) völlig nutzlos.
David Schmitt

Wenn Sie eine CHARSpalte 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 FOOauf BAR.
a_horse_with_no_name

4

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.


3

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.


3

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.


2

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.


2

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.


2

Zersplitterung. Char reserviert Platz und VarChar nicht. Für die Aktualisierung von varchar kann eine Seitenteilung erforderlich sein.


Aufgrund vieler anderer Faktoren kann es beim Aktualisieren einer CHARSpalte zu einer Seitenaufteilung kommen .
Rick James

1

Wenn Sie varchar-Werte verwenden, benötigt SQL Server zusätzliche 2 Bytes pro Zeile, um einige Informationen zu dieser Spalte zu speichern. Wenn Sie char verwenden, ist dies nur erforderlich, wenn Sie dies tun


0

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.


3
Welche Datenbanken implementieren VARCHAR auf diese Weise?
Troels Arvin

5
Ernsthaft, welche Datenbank implementiert es so? Was Sie beschreiben, gilt normalerweise für CHAR, nicht für VARCHAR.
Richard Simões

mysql konvertiert varchars in chars, wenn sich chars und varchars in derselben Tabelle befinden.
Malfist

Meine Interpretation der MySQL-Kommentare ist, dass dies nicht für den primären Tabellenspeicher gilt, sondern möglicherweise für temporäre Tabellen relevant ist, z. zum Gruppieren / Sortieren von Daten. dev.mysql.com/doc/refman/8.0/en/char.html stackoverflow.com/questions/262238/…
Thomas W

0

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.


Dies kann auch durch ansi_padding geändert werden. Wie Werte abgerufen werden
Edward
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.