4

我正在构建一个表来跟踪数据库中特定对象的历史记录。目前我有以下列:

HistoryId int IDENTITY(1,1) NOT NULL
HistoryDate datetimeoffset(7) NOT NULL 
HistoryTypeId int NOT NULL
HistoryDetails nvarchar(max) NULL

在大多数情况下,每个历史项目都将通过 HistoryTypeId 进行自我解释,因此 HistoryDe​​tails 要么为 Null,要么非常小。但是对于几个历史类型,细节数据会很大。是否可以使用 nvarchar(max) 处理所有记录,或者我应该将它分开并为需要超过 64 个字符的历史类型添加一个额外的列(见下文)?粗略估计,80%-90% 的记录不需要超过 64 个字符的详细信息,表中将有数百万条记录。

HistoryId int IDENTITY(1,1) NOT NULL
HistoryDate datetimeoffset(7) NOT NULL 
HistoryTypeId int NOT NULL
HistoryDetails nvarchar(64) NULL
HistoryDetailsMore nvarchar(max) NULL
4

3 回答 3

5

您不能NVARCHAR(MAX)在普通B-Tree索引中创建键的一部分(您仍然可以将其用作索引中的包含列)。

否则,只要列中的数据不超过行大小阈值,存储将相同。

由于您可能无论如何都不打算对该字段编制索引,因此最好将其创建为NVARCHAR(MAX).

即使您仍想对其进行索引(例如,使用 进行前缀搜索LIKE),您也可以创建一个计算NVARCHAR(450)列,在该列上创建一个索引,并将其添加到您的查询中以进行粗略过滤。

有关更多详细信息,请参阅我的博客中的此条目:

如果您打算只对小列进行精确搜索,请创建一个计算列,对其进行索引并像这样查询:

ALTER TABLE History ADD HistoryDetailsIndex AS SUBSTRING(HistoryDetails, 1, 50)

CREATE INDEX ix_mytable_typeid_details ON History (HistoryTypeId, HistoryDetailsIndex) INCLUDE (HistoryDetails)

SELECT  COUNT(*)
FROM    History
WHERE   HistoryTypeId = 123
        AND HistoryDetailsIndex LIKE 'string_prefix_up_to_50_characters%'
        AND HistoryDetails = 'string_prefix_up_to_50_characters_plus_everything_after_it'

这将只包括索引键中的第一个50字符HistoryDetails(将在LIKE条件中搜索),并将所有内容都包含在包含的列中。

如果您绝对确定永远不会搜索长度超过50字符的字符串,则可以省略包含的列并使用以下命令:

SELECT  COUNT(*)
FROM    History
WHERE   HistoryTypeId = 123
        AND HistoryDetailsIndex = 'string_prefix_up_to_50_characters'

这将使索引更短。

但是,如果您提供的字符串长度超过50字符,这将失败,因此如果您绝对确定永远不会搜索长字符串,请使用它。

于 2009-09-14T15:32:15.257 回答
0

由于您使用的是 nvarchar,因此您很可能已经支付了可变长度记录的开销,除非 SQLServer 覆盖小情况下的可变长度。但是,对于 nvarchar(64) 和 nvarchar(max) 之间的短记录,磁盘上的空间不应该改变。他们应该只占用适合其数据所需的空间。通常,该数字仅用于约束数据。如果您不想限制它,那么您不应该在使用您尚未支付的那两个之间支付罚款。

于 2009-09-14T15:29:19.630 回答
0

首先要知道 varchar(MAX) 最多可以存储 2gb 的空间,在幕后它实际上使用了一个 TEXT 值,随后它使用了比 varchar(8000) 更多或更少的处理。

如果您在 varchar(max) 中存储了大量较小的数据,它将被视为普通的 varchar 列,除非您超过 8000,否则它将被视为 varchar(max)。

该列是否已编入索引,还是您要编入索引?如果是这样,请避开 varchar(max)。

I would just pick a higher value, say varchar(255) and force users to fit to your database design and not the other way around.

于 2009-09-14T15:34:53.803 回答