在 SQL Server 中,根据其存储特性,某些数据类型被指定为属于以下组:
- 大值数据类型:varchar(max)、nvarchar(max) 和 varbinary(max)
- 大对象数据类型:text、ntext、image、varchar(max)、nvarchar(max)、varbinary(max) 和 xml
所以这些类型被定义为LOB 数据类型。当您问及binary data
我想您是在谈论binary
数据类型的数据时。
Binary
数据类型可以是两种类型之一:固定长度和可变长度。
具有最大字符数而不是 MAX 说明符的固定长度二进制数据类型或可变长度 varbinary 数据类型在第一种情况下始终存储在行中,在第二种情况下(可能)存储在行外,并且不是 LOB 数据类型。
另一方面,根据这种分类(来自同一篇 Technet 文章):
varchar(max)
, nvarchar(max)
, text
,ntext
数据类型是CHARACTER字符串,而不是 BINARY字符串。
所以 LOB 数据类型包括不是二进制字符串的 CHARACTER 字符串。
结论
二进制数据 <> LOB 数据
而当它是相同的唯一情况是,当你的数据被定义为VARBINARY(MAX)
回到关于如何存储 LOB 数据的评论中的问题。
如果该值是旧的遗留类型 ( text
, ntex
t, image
) 之一,则默认情况下将其存储在行外。
Off-row 意味着有一个来自数据记录的指针指向存储实际 LOB 值的记录的位置或存储 LOB 值的树的开头:
此图片来自Dmitri Korotkevitch 的 Pro SQL Server Internals 1st Edition。
但是您可以使用text in row
选项强制该值排成一行(显然带有限制)。
从 SQL Server 2005 开始引入了新的 LOB 数据类型,这些新类型:varchar(max)
, nvarchar(max)
,varbinary(max)
默认情况下存储在行中(当然有 8Kb 的限制)
………………………………………………………………………………………………………………………………………………………… .....
完成一张图。
还有另一种存储在行外的数据,即行溢出数据。
由于此功能,从 2005 年开始,不仅可以定义(就像在 2000 年一样)一些大小总和超过 8060 字节的可变长度列,而且可以插入将超过此限制的数据,其中一些值将被推离行(即值将存储在离行页面上,而在行中将只有一个指向存储在行溢出页面上的行的指针):
一个表每行最多可以包含 8,060 个字节。在 SQL Server 2008 中,对包含 varchar、nvarchar、varbinary、sql_variant 或 CLR 用户定义类型列的表放宽了此限制。这些列中每一列的长度仍必须在 8,000 字节的限制内;但是,它们的组合宽度可以超过 8,060 字节的限制。这适用于创建和修改 varchar、nvarchar、varbinary、sql_variant 或 CLR 用户定义类型的列,也适用于更新或插入数据时。
此限制不适用于 varchar(max)、nvarchar(max)、varbinary(max)、text、image 或 xml 列
(来自超过 8 KB 的行溢出数据)
在最大符扩展为varchar,nvarchar和varbinary数据类型的存储能力。varchar(max)、nvarchar(max) 和 varbinary(max) 统称为大值数据类型。您可以使用大值数据类型存储最多 2^31-1 字节的数据。
回到这个问题的起源,如何移动 LOB 数据。
当我们谈论将数据移动到另一个文件组以及我们在使用 LOB 数据时遇到的困难时,我们指的是 LOB 数据,而不是binary data
存储在二进制列 ( in-row
data) 中的数据。
从移动 LOB 数据怎么样?金伯利·L·特里普 (Kimberly L. Tripp)
在 SQL Server 2012 之前的版本中,无法使用联机操作构建或重建包含 LOB 列的索引。但是,即使使用离线索引构建或重建,也不会移动现有的 LOB 数据。一个例外是当您从分区表更改为非分区表时,反之亦然。老实说,围绕 LOB 数据的限制和要求有点奇怪。创建表时,您可以指定 TEXTIMAGE_ON。这允许该表的 LOB 数据驻留在数据驻留位置以外的文件组中。但是,此选项 (TEXTIMAGE_ON) 不可用于 CREATE INDEX 语句。
如果要将 LOBData 移动到另一个文件组怎么办?在 CREATE INDEX 语句期间不允许使用 TEXTIMAGE_ON 选项。因此,如果您想将 LOB 数据移动到另一个与数据不同的文件组,那么“游戏结束”如果不导出/导入或使用 INSERT/SELECT 或 SELECT INTO 就无法做到这一点。其中,最好的选择是 INSERT/SELECT,因为您需要先定义表(并且您可以准确地指定您希望数据和 LOB 数据驻留的位置),然后再复制它。但是,这是一个单一的大事务,当您迁移时,必须有一些停机时间来切换所有内容(通过删除原始表并重命名新创建的表)。而且,我什至还没有开始提到如果其他人引用了这张表会发生什么。这进一步使这个过程复杂化。
还有你的最后一个问题:
就二进制数据存储在单独的文件组中而言,它是否相同
存储 LOB 数据不需要单独的文件组。但是可以使用 TEXTIMAGE_ON 选项单独存储 LOB 数据:
TEXTIMAGE_ON { 文件组| "default" } 表示text、ntext、image、xml、varchar(max)、nvarchar(max)、varbinary(max) 和CLR 用户定义类型列(包括geometry 和geography)存储在指定的文件组中。
Varchar(max)、nvarchar(max)、varbinary(max)、xml 和大 UDT 值直接存储在数据行中,最大限制为 8000 字节,只要该值可以容纳记录即可。如果该值不适合记录,则将指针按行排序,并将其余部分存储在 LOB 存储空间中的行外。0 是默认值。TEXTIMAGE_ON 只改变“LOB 存储空间”的位置,不影响数据何时行内存储。使用 sp_tableoption 的行外选项的大值类型将整个 LOB 值存储在行外。
而定长binary
数据类型的数据就不能存储在单独的文件组中。这是不可能的,因为所有数据都存储在行中,并且在语法上是不可能的,因为
如果表中没有大值列,则不允许 TEXTIMAGE_ON
更多关于 TEXTIMAGE_ON 的信息:CREATE TABLE (Transact-SQL)