在 cast/convert 中使用 varchar(max) 而不是 varchar(n) 对性能有什么影响吗?

Ian*_*emp 1 performance sql-server datatypes

考虑以下表达式,它从日期时间值截断(不舍入)毫秒数:

declare @now datetime2 = sysdatetime();
select @now;
select convert(datetime2, convert(varchar(20), @now, 120));

-- Output
2021-07-30 09:38:33.5566666
2021-07-30 09:38:33.0000000
Run Code Online (Sandbox Code Playgroud)

请注意varchar(20). 我不喜欢那个特定的长度值,因为如果我应该更改我的数据类型,可能会丢失数据:

declare @now datetimeoffset = sysdatetimeoffset() at time zone 'Pacific Standard Time';
select @now;
select convert(datetimeoffset, convert(varchar(20), @now, 120));

-- Output
2021-07-30 02:39:12.7200000 -07:00
2021-07-30 02:39:12.0000000 +00:00 -- oops, we lost the time zone too!
Run Code Online (Sandbox Code Playgroud)

因此,我更愿意使用以下内容:

declare @now datetimeoffset = sysdatetimeoffset() at time zone 'Pacific Standard Time';
select @now;
select convert(datetimeoffset, convert(varchar(max), @now, 120)); -- note MAX not N

-- Output
2021-07-30 02:41:16.4566666 -07:00
2021-07-30 02:41:16.0000000 -07:00
Run Code Online (Sandbox Code Playgroud)

我的问题是,varchar(max)过度使用是否有任何有意义的性能影响varchar(N)- 包括但不限于内存分配?

我知道如果在 predicates 中使用(max)数据类型而不是(N)数据类型影响查询性能,但在我的特定示例中我没有这样做 - 只是分配varchars 然后在将它们转换回所需的数据类型后将它们扔掉。

Cha*_*ace 5

首先,回答你的问题:

是的,它会影响性能,因为需要分配空间来保存查询引擎中的大值。

在您的情况下,您也可以使用合适的大尺寸,例如varchar(50)可以轻松容纳您需要的任何东西。

但是你一开始就不应该做任何这些。

当四舍五入日期时,您不应该转换为varchar和返回,因为这会导致性能较差,以及涉及文化/风格的问题。

相反,使用标准的舍入技术:

declare @now datetimeoffset = sysdatetimeoffset() at time zone 'Pacific Standard Time';
declare @epoch datetimeoffset = CAST(@now AS date);
select dateadd(
    second,
    datediff(second, @epoch, @now at time zone 'utc'),
    @epoch) at time zone 'Pacific Standard Time';
Run Code Online (Sandbox Code Playgroud)