FORMAT 返回大行大小和数据大小

c44*_*548 7 sql-server sql-server-2012

我对我的一项发现感到惊讶,即使用 aFORMAT ()确实对行大小和数据大小有很大影响。它几乎是不应用的大小的 250 倍FORMAT ()

我的问题是:
1)为什么使用FORMAT()对大小有这么大的影响?对我来说,只有 1.23 美元与 1.23 美元的差异,这可能是 1 个字符的差异。这么大的尺寸有关系吗?

2) 为什么我们仍然鼓励FORMAT()在 SQL Server 中使用而不是使用字符串连接,如下所示。由于下面只有 2 倍的数据大小,使用格式返回 250 倍的数据大小。或者数据大小不是一个关键的衡量标准?

SELECT '$' + CONVERT(varchar(10), UnitPrice) FROM Sales.SalesOrderDetail;
Run Code Online (Sandbox Code Playgroud)

3) 数据大小为 464MB 是否意味着我将向客户端返回 464MB 的数据?

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

以下是我对 AdventureWorks2012 数据库的发现。

SELECT UnitPrice FROM Sales.SalesOrderDetail;
Run Code Online (Sandbox Code Playgroud)

实际行
数:121317
估计行数:121317估计行大小:15B
估计数据大小:1777KB

SELECT '$' + CONVERT(varchar (10), UnitPrice) FROM Sales.SalesOrderDetail;
Run Code Online (Sandbox Code Playgroud)

实际行数:121317
估计行大小:26B
估计数据大小:3060KB

SELECT FORMAT(UnitPrice, 'c') FROM Sales.SalesOrderDetail;
Run Code Online (Sandbox Code Playgroud)

实际行数:121317
估计行大小:4011B
估计数据大小:464MB

Aar*_*and 11

FORMAT()nvarchar(4000)至少在将整数和日期转换为字符串的情况下,有一个(公认未记录的)输出。该文件只是说...

返回值的长度由格式决定。

但是然后没有解释或提供任何例子。不过,您可以通过以下方式看到我所描述的内容:

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

EXEC tempdb.sys.sp_help N'#blat';
Run Code Online (Sandbox Code Playgroud)

结果是,xnvarchar8000的长度(这是字节数,而不是字符数)。

估计的行大小基于可变宽度值将占一半的假设。因此,它期望每行有 2,000 个字符(4,000 个字节)(即使您提供的特定参数不可能产生那么多字符)。我FORMAT()在另一个答案中证明了这一点(但不是特别地),与 varchar(255) 相比使用 varchar(5000) 会坏吗?

这是我更喜欢使用CONVERT()andTRY_CONVERT()等价物代替 的原因之一FORMAT(),尽管它有语法糖。至少对于那些您可以转换为定义的宽度而不是依赖它“由格式确定”的宽度。这可能或可能有助于估计大小,具体取决于查询。另一个例子展示了这里的好处(即使它需要更丑陋的代码):

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';
Run Code Online (Sandbox Code Playgroud)

结果:

a    float
b    nvarchar(4000)
c    varchar(13)
Run Code Online (Sandbox Code Playgroud)

我更喜欢使用的另一个原因CONVERT(),并TRY_CONVERT()FORMAT()很烂从性能的角度来看(见格式()是好的,所有的,但是......)。

另外请不要在没有varchar 指定 length 的情况下使用可变宽度类型。