Organización de tablas e índices

Las tablas y los índices se almacenan como una colección de páginas de 8 KB. En este tema se describe el modo en el que se organizan las páginas de tablas e índices.

Organización de tablas

En la siguiente ilustración se muestra la organización de una tabla. Una tabla está incluida en una o varias particiones y cada partición incluye filas de datos con una estructura de índice clúster o de montón. Las páginas del índice clúster o de montón se administran en una o varias unidades de asignación, según los tipos de columna de las filas de datos.

Organización de tablas con particiones

Particiones

Las páginas de tablas e índices están incluidas en una o varias particiones. Una partición es una unidad de organización de datos definida por el usuario. De forma predeterminada, una tabla o un índice solo incluyen una partición que contiene todas las páginas de tablas o índices. La partición se encuentra en un solo grupo de archivos. Una tabla o un índice con una sola partición es equivalente a la estructura organizativa de tablas e índices de versiones anteriores de SQL Server.

Cuando una tabla o un índice utilizan varias particiones, se crean particiones horizontales de los datos para que se asignen los grupos de filas a particiones individuales, en función de la columna especificada. Las particiones se pueden colocar en uno o varios grupos de archivos de la base de datos. La tabla o el índice se tratarán como una sola entidad lógica cuando se realicen consultas o actualizaciones en los datos. Para obtener más información, vea Tablas e índices con particiones.

Para ver las particiones utilizadas por una tabla o un índice, utilice la vista de catálogo sys.partitions (Transact-SQL).

Tablas, montones e índices clúster

Las tablas de SQL Server utilizan uno de estos dos métodos para organizar sus páginas de datos en una partición:

  • Las tablas agrupadas son tablas que tienen un índice clúster.

    Las filas de datos están almacenadas en un orden basado en la clave del índice clúster. El índice clúster se implementa como una estructura de árbol b que admite la recuperación rápida de las filas a partir de los valores de las claves del índice clúster. Las páginas de cada nivel del índice, incluidas las páginas de datos del nivel hoja, se vinculan en una lista con vínculos dobles. Sin embargo, la navegación de un nivel a otro se produce mediante valores de claves. Para obtener más información, vea Estructuras de ndices clúster.

  • Los montones son tablas que no tienen ningún índice clúster.

    Las filas de datos no se almacenan en ningún orden concreto, ni tampoco hay un orden concreto en la secuencia de las páginas de datos. Las páginas de datos no están vinculadas en una lista vinculada. Para obtener más información, vea Estructuras de montón.

Las vistas indizadas tienen la misma estructura de almacenamiento que las tablas agrupadas.

Cuando un montón o una tabla agrupada tienen varias particiones, cada una de ellas tiene una estructura de montón o de árbol b que incluye el grupo de filas de esa partición específica. Por ejemplo, si una tabla agrupada tiene cuatro particiones, hay cuatro árboles b, uno en cada partición.

Índices no clúster

Los índices no clúster tienen una estructura de árbol b similar a la de los índices clúster. La diferencia está en que los índices no clúster no tienen ningún efecto en el orden de las filas de datos. El nivel hoja contiene las filas del índice. Cada fila del índice contiene el valor de clave no agrupada, un localizador de filas y columnas incluidas o sin clave. El localizador apunta a la fila de datos que incluye el valor de clave. Para obtener más información, vea Estructuras de índices no agrupados.

Índices XML

En cada columna xml de la tabla se puede crear un índice XML principal y varios secundarios. Un índice XML es una representación dividida y persistente de los objetos binarios grandes (BLOB) XML de la columna de tipo de datos xml. Los índices XML se almacenan como tablas internas. Para ver información acerca de los índices xml, utilice las vistas de catálogo sys.xml_indexes o sys.internal_tables.

Para obtener más información acerca de los índices XML, vea Índices en columnas del tipo de datos XML.

Unidades de asignación

Una unidad de asignación es una colección de páginas de un montón o un árbol b utilizada para administrar los datos según su tipo de página. En la tabla siguiente se enumeran los tipos de unidades de asignación que se utilizan para administrar los datos en tablas e índices.

Tipo de unidad de asignación

Se utiliza para administrar

IN_ROW_DATA

Filas de datos o índices que incluyen todos los tipos de datos excepto los datos de objetos grandes (LOB).

Las páginas son del tipo datos o índice.

LOB_DATA

Datos de objetos grandes almacenados en uno o varios de los tipos de datos text, ntext, image, xml, varchar(max), nvarchar(max) o varbinary(max), o bien tipos definidos por el usuario CLR (CLR UDT).

Las páginas son del tipo texto e imagen.

ROW_OVERFLOW_DATA

Datos de longitud variable almacenados en varchar, nvarchar o varbinary, o bien columnas sql_variant que superan el límite de tamaño de las filas de 8.060 bytes.

Las páginas son del tipo texto e imagen.

Para obtener más información acerca de los tipos de páginas, vea Descripción de páginas y extensiones.

Un montón o un árbol b solamente puede tener una unidad de asignación de cada tipo en una partición específica. Para ver la información de unidades de asignación de tablas o índices, utilice la vista de catálogo sys.allocation_units.

Unidad de asignación IN_ROW_DATA

Por cada partición utilizada por una tabla (montón o tabla agrupada), un índice o una vista indizada, hay una unidad de asignación IN_ROW_DATA formada por una colección de páginas de datos. Esta unidad de asignación también incluye colecciones adicionales de páginas para implementar cada índice XML y no agrupado definido para la tabla o la vista. Las colecciones de páginas de cada partición de una tabla, índice o vista indizada están delimitadas por punteros de página en la vista del sistema sys.system_internals_allocation_units.

Nota importanteImportante

La vista del sistema sys.system_internals_allocation_units solo puede utilizarla internamente Microsoft SQL Server. La compatibilidad con versiones posteriores no está garantizada.

Cada partición de una tabla, índice o vista indizada tiene una fila en sys.system_internals_allocation_units identificada de forma única mediante un Id. de contenedor (container_id). El Id. de contenedor tiene una asignación uno a uno para partition_id en la vista de catálogo sys.partitions que mantiene la relación entre los datos de la tabla, el índice o la vista indizada de una partición y las unidades de asignación utilizadas para administrar los datos en la partición.

La asignación de páginas a una partición de tabla, índice o vista indizada se administra mediante una cadena de páginas IAM. La columna first_iam_page de sys.system_internals_allocation_units apunta a la primera página IAM de la cadena de páginas IAM que administran el espacio asignado a la tabla, el índice o la vista indizada de la unidad de asignación IN_ROW_DATA.

sys.partitions devuelve una fila para cada partición de una tabla o un índice.

  • Un montón tiene una fila en sys.partitions con index_id = 0.

    La columna first_iam_page de sys.system_internals_allocation_units apunta a la cadena IAM de la colección de páginas de datos de montón de la partición especificada. El servidor utiliza las páginas IAM para buscar las páginas en la colección de páginas de datos, puesto que no están vinculadas.

  • Un índice clúster de una tabla o vista tiene una fila en sys.partitions con index_id = 1.

    La columna root_page de sys.system_internals_allocation_units apunta a la parte superior del árbol b del índice clúster en la partición especificada. El servidor utiliza el árbol b del índice para buscar las páginas de datos en la partición.

  • Cada índice no clúster creado para una tabla o vista tiene una fila en sys.partitions con index_id > 1.

    La columna root_page de sys.system_internals_allocation_units apunta a la parte superior del árbol b del índice no clúster en la partición especificada.

  • Cada tabla que tiene al menos una columna LOB también tiene una fila en sys.partitions con index_id > 250.

    La columna first_iam_page apunta a la cadena de páginas IAM que administra las páginas de la unidad de asignación LOB_DATA.

Unidad de asignación ROW_OVERFLOW_DATA

Por cada partición utilizada por una tabla (montón o tabla agrupada), un índice o una vista indizada, hay una unidad de asignación ROW_OVERFLOW_DATA. Esta unidad de asignación no tiene ninguna página hasta que una fila de datos con columnas de longitud variable (varchar, nvarchar, varbinary o sql_variant) de la unidad de asignación IN_ROW_DATA supera el límite de tamaño de fila de 8 KB. Cuando se alcanza la limitación de tamaño, SQL Server mueve la columna más ancha de esa fila a una página de la unidad de asignación ROW_OVERFLOW_DATA. Se mantiene un puntero de 24 bytes a estos datos no consecutivos en la página original.

Las páginas de texto o imagen de la unidad de asignación ROW_OVERFLOW_DATA se administran del mismo modo que las de la unidad de asignación LOB_DATA; es decir, mediante una cadena de páginas IAM.

Unidad de asignación LOB_DATA

Cuando una tabla o un índice tiene uno o varios tipos de datos LOB, se asignará una unidad de asignación LOB_DATA por partición para administrar el almacenamiento de esos datos. Los tipos de datos LOB incluyen text, ntext, image, xml, varchar(max), nvarchar(max), varbinary(max) y los tipos definidos por el usuario CLR.

Ejemplo de unidad de asignación y partición

En el ejemplo siguiente se devuelven los datos de unidad de asignación y partición para dos tablas: DatabaseLog, un montón con datos LOB e índices no clúster, y Currency, una tabla agrupada sin datos LOB y un índice no clúster. Ambas tablas tienen una sola partición.

USE AdventureWorks2008R2;
GO
SELECT o.name AS table_name,p.index_id, i.name AS index_name , au.type_desc AS allocation_type, au.data_pages, partition_number
FROM sys.allocation_units AS au
    JOIN sys.partitions AS p ON au.container_id = p.partition_id
    JOIN sys.objects AS o ON p.object_id = o.object_id
    JOIN sys.indexes AS i ON p.index_id = i.index_id AND i.object_id = p.object_id
WHERE o.name = N'DatabaseLog' OR o.name = N'Currency'
ORDER BY o.name, p.index_id;

El conjunto de resultados es el siguiente. Tenga en cuenta que la tabla DatabaseLog utiliza los tres tipos de unidad de asignación, pues contiene tipos de páginas de datos y de texto e imagen. La tabla Currency no tiene datos LOB, pero tiene la unidad de asignación necesaria para administrar las páginas de datos. Si más adelante se modifica la tabla Currency para incluir una columna de tipo de datos LOB, se creará una unidad de asignación LOB_DATA para administrar esos datos.

table_name  index_id index_name               allocation_type     data_pages  partition_number 
----------- -------- -----------------------  ---------------     -----------  ------------
Currency    1        PK_Currency_CurrencyCode IN_ROW_DATA         1           1
Currency    3        AK_Currency_Name         IN_ROW_DATA         1           1
DatabaseLog 0        NULL                     IN_ROW_DATA         160         1
DatabaseLog 0        NULL                     ROW_OVERFLOW_DATA   0           1
DatabaseLog 0        NULL                     LOB_DATA            49          1
(5 row(s) affected)