行内数据
小到中等大小的大值类型(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 指定 OFF 或 0 选项值来禁用此选项。
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 文本和图像函数(例如 dbreadtext 和 dbwritetext)将无法在表上使用。