FORMAT gibt große Zeilen- und Datengröße zurück

7

Ich bin überrascht von einer meiner Erkenntnisse, dass die Verwendung von a FORMAT ()einen sehr großen Einfluss auf die Zeilengröße und Datengröße hat. Es ist fast 250x größer als die Größe, die nicht angewendet wird FORMAT ().

Meine Frage ist:
1) Warum hat die Verwendung FORMAT()einen so großen Einfluss auf die Größe? Für mich beträgt der Unterschied nur 1,23 gegenüber 1,23 US-Dollar, was wahrscheinlich einem Unterschied von 1 Zeichen entspricht. Und spielt es bei so großer Größe eine Rolle?

2) Warum sollten wir immer noch die Verwendung FORMAT()in SQL Server anstelle der folgenden Verkettung von Zeichenfolgen empfehlen? Da unten nur die 2-fache Datengröße angegeben ist und die Verwendung des Formats die 250-fache Datengröße zurückgibt. ODER ist diese Datengröße keine kritische Messung?

SELECT '$' + CONVERT(varchar(10), UnitPrice) FROM Sales.SalesOrderDetail;

3) Bedeutet eine Datengröße von 464 MB, dass ich 464 MB Daten an den Client zurückgeben werde?

================================================== ======

Unten sind meine Ergebnisse mit der AdventureWorks2012-Datenbank.

SELECT UnitPrice FROM Sales.SalesOrderDetail;

Tatsächliche Anzahl der Zeilen: 121317
Geschätzte Anzahl der Zeilen: 121317
Geschätzte Zeilengröße : 15B
Geschätzte Datengröße: 1777 KB

SELECT '$' + CONVERT(varchar (10), UnitPrice) FROM Sales.SalesOrderDetail;

Tatsächliche Anzahl der Zeilen: 121317
Geschätzte Zeilengröße : 26B
Geschätzte Datengröße: 3060 KB

SELECT FORMAT(UnitPrice, 'c') FROM Sales.SalesOrderDetail;

Tatsächliche Anzahl der Zeilen: 121317
Geschätzte Zeilengröße: 4011B
Geschätzte Datengröße: 464 MB

c448548
quelle

Antworten:

11

FORMAT()hat eine (zugegebenermaßen undokumentierte) Ausgabe von nvarchar(4000), zumindest bei der Konvertierung von Ints und Datumsangaben in Strings. Die Dokumentation sagt einfach ...

Die Länge des Rückgabewerts wird durch das Format bestimmt .

Aber dann erklärt oder liefert keine Beispiele. Sie können jedoch sehen, was ich beschreibe mit:

SELECT TOP (1) object_id, x = FORMAT(object_id, 'en-us') 
  INTO #blat FROM sys.all_objects;

EXEC tempdb.sys.sp_help N'#blat';

Ergebnis ist, dass xeinnvarchar mit einer Länge von 8000 (das ist die Anzahl der Bytes, die Anzahl von Zeichen).

Die geschätzte Zeilengröße basiert auf der Annahme, dass die Werte für die variable Breite zur Hälfte ausgefüllt werden. Es werden also 2.000 Zeichen (4.000 Byte) in jeder Zeile erwartet (selbst wenn die von Ihnen angegebenen Parameter möglicherweise nicht zu so vielen Zeichen führen können). Ich demonstriere dies (aber nicht FORMAT()speziell mit) in einer anderen Antwort: Wäre die Verwendung von varchar (5000) im Vergleich zu varchar (255) schlecht?

Dies ist ein Grund, warum ich trotz seines syntaktischen Zuckers lieber Äquivalente CONVERT()als TRY_CONVERT()Äquivalente verwende FORMAT(). Zumindest mit diesen können Sie in eine definierte Breite konvertieren, anstatt sich darauf zu verlassen, dass sie "vom Format bestimmt" wird. Welche kann oder kann helfen, geschätzte Größe, abhängig von der Abfrage. Ein weiteres Beispiel, das den Vorteil hier demonstriert (obwohl es hässlicheren Code erfordert):

DECLARE @m float = 32.74532323;

SELECT 
    a = @m, 
    b = FORMAT(@m, 'c'), 
    c = '$' + CONVERT(varchar(12), CONVERT(decimal(8,2),@m))
 INTO #splunge 
 FROM sys.all_objects;

EXEC tempdb.sys.sp_help N'#splunge';

Ergebnisse:

a    float
b    nvarchar(4000)
c    varchar(13)

Ein weiterer Grund , warum ich zu bevorzugen CONVERT()und TRY_CONVERT()ist , dass FORMAT()saugt aus Sicht der Leistung (siehe FORMAT () ist schön und alle, aber ... ).

Verwenden Sie auch niemals Typen mit variabler Breite, varchar ohne eine Länge anzugeben .

Aaron Bertrand
quelle
Kann ich daraus schließen, dass die geschätzte Datengröße für die Rückgabe der Ergebnisdatengröße an den Client nicht relevant ist? Die Rückgabe der Ergebnisdatengröße an den Client entspricht der tatsächlichen Größe in Abhängigkeit von der Anzahl der zurückgegebenen Zeichen. Dies bedeutet, dass mein Client für die Verwendung von FORMAT () und für die Verwendung von CONVERT () dieselbe Ergebnisgröße erhalten würde, solange beide eine ähnliche Ausgabe erzeugen.
c448548
1
@ c448548 Ja, ich glaube ich habe genau das gezeigt. SQL Server misst die Ausgabe nicht wirklich, da es den Speicherbedarf erraten muss, bevor es tatsächlich Daten sieht. Könnte es klüger sein? Sicher. Aber es ist nicht heute.
Aaron Bertrand
Ein Punkt bei FORMAT ist, dass einige Verwendungen - z. B. Währung - viele funktionale Aspekte haben, die CONVERT nicht abdeckt. (Dezimaltrennzeichen, Darstellung von Negativen usw. usw.). Wenn diese Verhaltensweisen wichtig sind, würde ich den Leistungseinbruch schlucken. Und konvertieren Sie dann zu einem vernünftigen Varchar (n), um das von Ihnen hervorgehobene Kernproblem abzudecken :)
Paul Holmes