行内数据

小到中等大小的大值类型(varchar(max)、nvarchar(max)、varbinary(max) 和 xml)和大型对象 (LOB) 数据类型(text、ntext 和 image)都可以存储在数据行中。该行为可以通过在 sp_tableoption 系统存储过程中使用以下两个选项来控制:用于大值类型的 large value types out of row 选项,以及用于大型对象类型的 text in row 选项。这两个选项最适用于这样的表:其中上述任意一种数据类型的数据值通常在一个单元中读/写,并且引用表的大多数语句都将引用此类数据。在行内存储的数据不一定有用,这取决于使用情况或工作负荷特征。

重要说明重要提示

在 SQL Server 的未来版本中将删除 text in row 选项。避免在新的开发工作中使用该选项,并计划修改当前使用 text in row 的应用程序。建议使用 varchar(max)、nvarchar(max) 或 varbinary(max) 数据类型存储大型数据。若要控制这些数据类型的行内和行外行为,请使用 large value types out of row 选项。

除非 text in row 选项设置为 ON 或特定的行内限制,否则 text、ntext 或 image 字符串都将是在数据行外存储的大型字符或二进制字符串(最多 2 GB)。数据行只包括一个 16 字节的文本指针,该指针指向一个内部指针构成的树的根节点。这些指针映射存储字符串片段的页。有关 text、ntext 或 image 字符串存储的详细信息,请参阅使用 Text 和 Image 数据

可以为包含 LOB 数据类型列的表设置 text in row 选项。还可以指定 text in row 选项限制,范围从 24 到 7,000 字节。

同样,除非 large value types out of row 选项设置为 ON,否则会尽可能将 varchar(max)、nvarchar(max)、varbinary(max) 和 xml 列存储在数据行内。如果如此设置,则可以的话 SQL Server 数据库引擎将尝试容纳此特定值,否则会将其推到行外。如果 large value types out of row 设置为 ON,则上述值将存储在行外而只有 16 字节的文本指针存储在记录中。

注意注意

large value types out of row 设置为 OFF 时,用于大型值数据类型的最大行内存储量设置为 8,000 字节。与 text in row 选项不同,您不能指定表中列的行内限制。

将表配置为直接在数据行中存储大型值类型或大型对象数据类型时,如果存在以下情况之一,实际的列值都将存储在行内:

  • 字符串的长度小于为 text、ntext 和 image 列指定的限制值。

  • 数据行中有足够的可用空间容纳字符串。

当大型值类型或大型对象数据类型列值存储在数据行中时,数据库引擎不必访问单独的页或页集来读/写字符或二进制字符串。这便使读/写行内字符串的速度与读/写大小受限制的 varchar、nvarchar 或 varbinary 字符串的速度大致一样。同样,当值存储在行外时,数据库引擎将引发读/写附加页。

对于大型对象数据类型,如果存储字符串所需的空间比 text in row 选项限制或行中的可用空间大,则本应存储在指针树根节点中的指针集将存储在行中。如果存在以下情况之一,指针将存储在行中:

  • 存储指针所需的空间量比 text in row 选项限制指定的空间量小。

  • 数据行中有足够的可用空间容纳指针。

当指针从根节点移至行本身时,数据库引擎不需要使用根节点。这样便可以在读/写字符串时不必访问页。从而可以提高性能。

如果使用根节点,它们将存储为 LOB 页中的一个字符串片段,并且最多可以包含 5 个内部指针。数据库引擎需要行具有 72 字节的空间来存储行内字符串的五个指针。如果 text in row 选项为 ON 或 large value types out of row 选项为 OFF 时行中没有足够的空间来容纳指针,数据库引擎可能必须分配一个 8K 的页来容纳它们。如果值的数据长度超过 40,200 字节,则需要 5 个以上的行内指针,此时只有 24 字节存储在主行中,而其他数据页被分配在 LOB 存储空间中。

当大型字符串存储在行中时,它们将与可变长度字符串的存储方式相似。数据库引擎将对列按大小以降序排序,并将值推到行外,直到剩余的列容纳在数据页 (8K) 中。

启用和禁用 large value types out of row 选项

可以按照下列方式通过使用 sp_tableoption 来为表启用 large value types out of row 选项:

sp_tableoption N'MyTable', 'large value types out of row', 'ON'

如果指定为 OFF,则 varchar(max)、nvarchar(max)、varbinary(max) 和 xml 列的行内限制将设置为 8,000 个字节。只有 16 字节的根指针存储在行内,而值存储在 LOB 存储空间中。对于其中大多数语句都不引用大型值类型列的表,建议将该选项设置为 ON。将这些列存储在行外意味着每页可以容纳更多的行,因此减少了扫描表所需的 I/O 操作的数量。

当该选项的值设置为 OFF 时,许多字符串可能最终会存储在行内,从而可能减少每页上容纳的数据行数。如果大多数引用表的语句都不访问 varchar(max)、nvarchar(max)、varbinary(max) 和 xml 列,则减少页中的行数会增加处理查询时必须读取的页数。减少每页上的行数会增加页的数量,优化器找不到可用的索引时可能必须扫描这些页。

也可以使用 sp_tableoption 禁用行外选项:

sp_tableoption N'MyTable', 'large value types out of row', 'OFF'

如果 large value types out of row 选项的值发生更改,则现有的 varchar(max)、nvarchar(max)、varbinary(max) 和 xml 类型的值不会立即转换。字符串的存储会随着字符串的更新而变化。任何插入表中的新值都将根据有效的表选项存储。

若要检查特定表的 large value types out of row 选项的值,请查询 sys.tables 目录视图的 large_value_types_out_of_row 列。如果表未启用 large value types out of row,则此列为 0;如果大值类型存储在行外,则此列为 1。

启用和禁用 text in row 选项

可以按照以下方式通过使用 sp_tableoption 为表启用 text in row 选项:

sp_tableoption N'MyTable', 'text in row', 'ON'

或者,可以为能够在数据行中存储的 text、ntext 和 image 字符串长度指定从 24 到 7,000 字节的最大限制:

sp_tableoption N'MyTable', 'text in row', '1000'

如果指定的是 ON 而不是一个特定的限制,则此限制的默认值为 256 字节。该默认值使您能够从使用 text in row 选项中获得最多的性能收益。虽然通常情况下,不应使该值的设置低于 72,但也不应将其设置的过高。该设置尤其适用于其中大多数语句都不引用 text、ntext 和 image 列的表,或其中有多个 text、ntext 和 image 列的表。

如果设置了较大的 text in row 限制,且行本身存储了许多字符串,则可以显著减少存储在每页上的数据行数。如果大多数引用表的语句都不访问 text、ntext 或 image 列,则减少页中的行数会增加处理查询时必须读取的页数。减少每页上的行会增加索引和页的大小,优化器找不到可用的索引时可能必须扫描这些索引和页。text in row 限制的默认值为 256,这足以确保小型字符串和根文本指针可以存储在行中,但不会使每页上的行减少太多以至影响性能。

对于具有表数据类型的变量和用户定义函数(返回)返回的表,text in row 选项自动设置为 256。不能更改该设置。

也可以使用 sp_tableoption 指定 OFF0 选项值来禁用此选项。

sp_tableoption N'MyTable', 'text in row', 'OFF'

若要检查特定表的 text in row 选项的值,请查询 sys.tables 目录视图的 text_in_row_limit 列。如果没有为表启用 text in row,则此列为 0;如果设置了行内限制,则此列为大于 0 的值。

使用 text in row 选项的效果

text in row 选项具有以下效果:

  • 启用 text in row 选项后,可以使用 TEXTPTR、READTEXT、UPDATETEXT 或 WRITETEXT 语句读取或修改表中存储的任何 text、ntext 或 image 值的部分。在 SELECT 语句中,可以读取整个 text、ntext 或 image 字符串,或使用 SUBSTRING 函数读取部分字符串。所有引用表的 INSERT 或 UPDATE 语句都必须指定完整的字符串,并且不能只修改 text、ntext 或 image 字符串的一部分。

  • 当第一次启用 text in row 选项时,现有的 text、ntext 或 image 字符串不会立即转换为行内字符串。仅当随后更新字符串时,这些字符串才转换成行内字符串。启用 text in row 选项后插入的任何 text、ntext 或 image 字符串都将作为行内字符串插入。

  • 禁用 text in row 选项可能是长时间运行的日志记录操作。表被锁定,并且所有行内 text、ntext 和 image 字符串都将转换为常规 text、ntext 和 image 字符串。运行命令所需的时间和已经修改的数据量,取决于必须从行内字符串转换为常规字符串的 text、ntext 和 image 字符串的数量。

  • text in row 选项不会影响 SQL Server Native Client OLE DB 访问接口或 SQL Server Native Client ODBC 驱动程序的操作,而只会加快访问 text、ntext 和 image 数据的速度。

  • 启用 text in row 选项后,DB-Library 文本和图像函数(例如 dbreadtextdbwritetext)将无法在表上使用。

请参阅

概念

其他资源