简体   繁体   English

表变量列中的nvarchar(max)与nvarchar(n)

[英]nvarchar(max) versus nvarchar(n) in table variable columns

I do a lot of work with table variables before finally presenting result sets to the user. 在最终向用户呈现结果集之前,我对表变量做了很多工作。 For example, I might pull in a whole load of columns from many different tables like this: 例如,我可能从许多不同的表中拉入一大堆列,如下所示:

DECLARE @tmp TABLE
(
ID int,
username nvarchar(50),  -- data taken from tbl_Users
site nvarchar(50),      -- data taken from tbl_Sites
region nvarchar(100),   -- data taken from tbl_Regions
currency nvarchar(5)    -- data taken from tbl_Currencies
)

I spend a lot of time looking through the Object Explorer to ensure that the data length of the columns in correct (matches the original tables). 我花了很多时间浏览对象资源管理器以确保列的数据长度正确(与原始表匹配)。 Sometimes if I change the table schema but don't update all the procedures, I might get caught out with a truncation error. 有时,如果我更改表模式但不更新所有过程,我可能会遇到截断错误。

Is there any issue with taking a lazy approach and just doing this: 采取懒惰的做法是否有任何问题:

DECLARE @tmp TABLE
(
ID int,
username nvarchar(max),
site nvarchar(max),
region nvarchar(max),
currency nvarchar(max)
)

Does nvarchar(max) actually use up any more memory or this the allocated memory based on the data size? nvarchar(max)实际上是否会占用更多内存,或者这是基于数据大小分配的内存? Are there any other gotchas? 还有其他陷阱吗?

Please note that I am aware of third-party tools for jumping to the definition, but that's not what I'm asking. 请注意,我知道跳转到定义的第三方工具,但这不是我要求的。

UPDATE UPDATE

The duplicate question has value, but the question is not identical IMHO. 重复的问题有价值,但问题不一样恕我直言。 The duplicate revolves around the design of actual tables, not table variables . 副本围绕实际表的设计而不是表变量 However, there is some merit in the answers, namely: 但是,答案中有一些优点,即:

  • nvarchar(max) vs nvarchar(8000) are no different in resource usage until 8000+ data lengths nvarchar(max)vs nvarchar(8000)在资源使用方面没有差异,直到8000+数据长度
  • Business logic layers rely on structure and meaningful data, so specifying a column size that compliments the original provides value 业务逻辑层依赖于结构和有意义的数据,因此指定与原始值相称的列大小可提供值

In that sense, it would seem that it is fine to use nvarchar(max) in table variables instead of nvarchar(n) , but it has a reliability and performance risk in some environments. 从这个意义上说,在表变量中使用nvarchar(max)而不是nvarchar(n)似乎没问题,但在某些环境中它具有可靠性和性能风险。 If you think this should be deleted then fair enough (but please stop arguing I appreciate all input!) 如果你认为这应该被删除然后公平(但请停止争论我欣赏所有输入!)

I can't think of any reason nvarchar(max) in a table variable would have any pitfalls that are different from using nvarchar(max) in a table ( the downsides of which are explained in this question ), except for the pitfalls that are due to the differences between table variables and temp/permanent tables in the first place (eg terrible statistics, no secondary indexes, etc). 我想不出任何理由nvarchar(max)在一个表变量中会有任何与在表中使用nvarchar(max)不同的陷阱( 在这个问题中解释其缺点 ),除了陷阱由于表变量和临时/永久表之间的差异(例如,可怕的统计数据,没有二级索引等)。 Martin Smith draws a great comparison between table variables and temp tables here . Martin Smith在这里对表变量和临时表进行了很好的比较

You still have to worry about certain issues, for example if you are using ancient technology like classic ASP/ADO, you may find that you have to list MAX columns last to ensure the results are accurate. 您仍然需要担心某些问题,例如,如果您使用古典技术(如经典ASP / ADO),您可能会发现必须最后列出MAX列以确保结果准确。 I explained this here back in 2000, before MAX types were introduced ; 我在2000年之前解释了这一点,然后才引入MAX类型 ; but they have the same problems in those old providers as TEXT / NTEXT . 但是他们在TEXT / NTEXT旧提供商中遇到了同样的问题。 Highly unlikely you are using that technology, but thought I would mention it just in case. 你不太可能使用这种技术,但我想我会提到它以防万一。

I'd suggest, though, that you just take the hit and script the correct types when you're writing the code. 不过,我建议你在编写代码时只需要点击并编写正确的类型。 They are easy to derive from the metadata (eg sys.columns or right-clicking the table and saying script as > create to > clipboard) and doing so will prevent any problems (such as the one @JC. mentioned above regarding mismatched lengths, possibly leading to overflow/truncation). 它们很容易从元数据派生(例如sys.columns或右键单击表并将脚本称为>创建到>剪贴板),这样做可以防止出现任何问题(例如上面提到的关于不匹配长度的@JC。 )可能导致溢出/截断)。

Also, as I meant to imply earlier, if you have any substantial number of rows (thanks @Stuart), you should consider #temp tables instead. 另外,正如我之前暗示的那样,如果你有大量的行(感谢@Stuart),你应该考虑使用#temp表。 I still think that whatever you choose should be well-defined. 我仍然认为无论你选择什么都应该明确。 The only benefit to using MAX for everything in this scenario is that it allows you to be lazy, while opening you up to a whole lot of risk. 在这种情况下,将MAX用于所有事情的唯一好处是它可以让你变得懒惰,同时为你带来很大的风险。 You write your code once, but your users run it countless time. 您编写一次代码,但是您的用户无数次地运行它。 Spend the extra couple of minutes to make your data types correct, even if it means you have to correct it twice later should the schema change. 花费额外的几分钟来使您的数据类型正确,即使这意味着如果架构发生更改,您必须稍后更正两次。

And as for the memory usage of nvarchar(max) , yes, this could change your performance. 至于nvarchar(max)的内存使用情况,是的,这可能会改变你的性能。 See this blog post for some evidence . 有关证据,请参阅此博客文章 Partial relevant snippet, with my spelling/grammar corrections: 部分相关片段,我的拼写/语法更正:

So if you are sure that the length of your nvarchar column will be less than 8000, then do not define the column as nvarchar(max) but rather define it as nvarchar(fixedlength) wherever possible. 因此,如果您确定nvarchar列的长度小于8000,则不要将列定义为nvarchar(max),而是尽可能将其定义为nvarchar(fixedlength)。 The main advantages I see for using fixed length are: 我看到使用固定长度的主要优点是:

Memory grant could be a big issue where the server is already memory starved. 内存授权可能是服务器已经缺乏内存的一个大问题。 As expected row size is more the optimizer will estimate more memory grant and this value will be much higher than actually required and this would be a waste of a resource as precious as memory. 正如预期的行大小更多,优化器将估计更多的内存授予,这个值将远远高于实际需要,这将浪费像内存一样宝贵的资源。 If you have couple of queries which are using nvarchar(max) column and sorting is needed then server might have memory related issues. 如果您有几个使用nvarchar(max)列的查询并且需要排序,则服务器可能存在与内存相关的问题。 This could be a big perf issue. 这可能是一个很大的问题。

The other advantages he listed had to do with indexes. 他列出的其他优势与索引有关。 Not an issue with table variables anyway, since you can't create secondary indexes (before SQL Server 2014). 无论如何,表变量都不是问题,因为您无法创建二级索引(在SQL Server 2014之前)。

But once again, this potential problem is really no different no matter which type of table structure you are pulling the data from - temp table, table variable, permanent table, etc. 但是再一次,无论你从哪个类型的表结构中提取数据,这个潜在的问题都没有什么不同 - 临时表,表变量,永久表等。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM