2009-05-20 19 views
130

¿Puede crear un índice en una variable de tabla en SQL Server 2000?Crear un índice en una variable de tabla

decir

DECLARE @TEMPTABLE TABLE (
     [ID] [int] NOT NULL PRIMARY KEY 
     ,[Name] [nvarchar] (255) COLLATE DATABASE_DEFAULT NULL 
) 

¿Puedo crear un índice en Nombre?

+3

La creación de ambos tipos de tablas temporales tiene un costo; y si tiene tantos datos que necesita un índice, tal vez sea hora de usar una tabla real; que configuró para que sea seguro para las transacciones; filtrar por spid o id de usuario y luego borrarlo al final. Tablas reales v tablas temporales tienen sus altibajos, pero si el rendimiento es un problema; Pruébalo con una mesa real también. – u07ch

+0

Una tabla temporal 'IS' es una tabla real, simplemente desaparece cuando termina. La diferencia real (aparte de que desaparecerá automáticamente) es que está en TempDB. Esto es realmente enorme cuando se trata de índices y restricciones, ya que podría terminar con conflictos de nombres, no solo con otras ejecuciones de su código, sino también con la ejecución del código en otras bases de datos en su instancia. – bielawski

+0

@bielawski esta es una variable de tabla no una tabla temporal. Las variables de tabla no permiten restricciones explícitamente nombradas, los nombres generados por el sistema garantizan que son únicos.Permiten índices con nombre a partir de 2014, pero eso no es un problema ya que los índices solo necesitan ser nombrados de manera única dentro de un objeto, no a través de los objetos. –

Respuesta

256

La pregunta está etiquetada como SQL Server 2000, pero para el beneficio de las personas que están desarrollando la última versión, la abordaré primero.

SQL Server 2014

Además de los métodos de la adición de índices basados ​​restricción se discuten a continuación SQL Server 2014 también permite índices no únicos para especificar directamente con la sintaxis de línea en las declaraciones de variables de mesa.

La sintaxis de ejemplo para eso está a continuación.

/*SQL Server 2014+ compatible inline index syntax*/ 
DECLARE @T TABLE (
C1 INT INDEX IX1 CLUSTERED, /*Single column indexes can be declared next to the column*/ 
C2 INT INDEX IX2 NONCLUSTERED, 
     INDEX IX3 NONCLUSTERED(C1,C2) /*Example composite index*/ 
); 

índices filtrados e índices con columnas incluidas actualmente no pueden ser declaradas con esta sintaxis sin embargo SQL Server 2016 relaja esto un poco más lejos. Desde CTP 3.1 ahora es posible declarar índices filtrados para variables de tabla. Por RTM que puede ser el caso que incluyen columnas también están permitidos, pero la posición actual es que "will likely not make it into SQL16 due to resource constraints"

/*SQL Server 2016 allows filtered indexes*/ 
DECLARE @T TABLE 
(
c1 INT NULL INDEX ix UNIQUE WHERE c1 IS NOT NULL /*Unique ignoring nulls*/ 
) 

SQL Server 2000 - 2012

¿Puedo crear una índice en Nombre?

Respuesta corta: Sí.

DECLARE @TEMPTABLE TABLE (
    [ID] [INT] NOT NULL PRIMARY KEY, 
    [Name] [NVARCHAR] (255) COLLATE DATABASE_DEFAULT NULL, 
    UNIQUE NONCLUSTERED ([Name], [ID]) 
) 

Una respuesta más detallada está debajo.

Las tablas tradicionales en SQL Server pueden tener un índice agrupado o están estructuradas como heaps.

Los índices agrupados pueden declararse como exclusivos para no permitir valores de clave duplicados o no predeterminados como no exclusivos. Si no es exclusivo, SQL Server agrega silenciosamente un uniqueifier a las claves duplicadas para que sean únicas.

Los índices no agrupados también se pueden declarar explícitamente como únicos. De lo contrario, para el caso no único SQL Server adds the row locator (clave de índice agrupado o RID para un montón) para todas las claves de índice (no solo para las duplicadas), esto garantiza nuevamente que son únicas.

En SQL Server 2000 - 2012 los índices en las variables de la tabla solo se pueden crear implícitamente al crear una restricción UNIQUE o PRIMARY KEY. La diferencia entre estos tipos de restricciones es que la clave primaria debe estar en columna (s) no anulables. Las columnas que participan en una restricción única pueden ser anulables. (aunque la implementación de restricciones únicas de SQL Server en presencia de NULL s no es la especificada en el estándar SQL). Además, una tabla solo puede tener una clave principal pero múltiples restricciones únicas.

Ambas limitaciones lógicas se implementan físicamente con un índice único. Si no se especifica expresamente lo contrario la PRIMARY KEY se convertirá en el índice agrupado y restricciones únicas no agrupado pero este comportamiento puede ser anulado por la especificación de CLUSTERED o NONCLUSTERED explícitamente con la declaración de restricción (sintaxis Ejemplo)

DECLARE @T TABLE 
(
A INT NULL UNIQUE CLUSTERED, 
B INT NOT NULL PRIMARY KEY NONCLUSTERED 
) 

Como resultado de lo anterior los siguientes índices pueden ser creados de forma implícita en las variables de la tabla de SQL Server 2000 - 2012.

+-------------------------------------+-------------------------------------+ 
|    Index Type    | Can be created on a table variable? | 
+-------------------------------------+-------------------------------------+ 
| Unique Clustered Index    | Yes         | 
| Nonunique Clustered Index   |          | 
| Unique NCI on a heap    | Yes         | 
| Non Unique NCI on a heap   |          | 
| Unique NCI on a clustered index  | Yes         | 
| Non Unique NCI on a clustered index | Yes         | 
+-------------------------------------+-------------------------------------+ 

El último requiere un poco de explicación. En la definición de variable de tabla al principio de esta respuesta, el no único índice no agrupado en Name se simula mediante un índice único en Name,Id (recuerde que SQL Server agregaría silenciosamente la clave de índice agrupado a la clave NCI no única de todos modos)

También se puede lograr un índice agrupado no exclusivo agregando manualmente una columna IDENTITY para actuar como un único elemento.

DECLARE @T TABLE 
(
A INT NULL, 
B INT NULL, 
C INT NULL, 
Uniqueifier INT NOT NULL IDENTITY(1,1), 
UNIQUE CLUSTERED (A,Uniqueifier) 
) 

Pero esto no es una simulación exacta de cómo un índice agrupado no único normalmente sería en realidad ser implementada en SQL Server como esto se suma la "Uniqueifier" a todas las filas. No solo aquellos que lo requieren.

+1

Nota: la solución 2000-2012 funciona solo si la columna de texto es <= 900 bytes. es decir. varchar (900), nvarchar (450) –

+1

@AndreFigueiredo Sí, ese es el tamaño máximo para una clave de índice en tablas permanentes también en esas versiones. –

+0

Solo quería señalar que la respuesta de SQL 2014 funciona bien en Azure. Gracias Martin! – Jaxidian

11

Debe entenderse que, desde el punto de vista del rendimiento, no existen diferencias entre las tablas @temp y #temp que favorecen las variables. Residen en el mismo lugar (tempdb) y se implementan de la misma manera. Todas las diferencias aparecen en características adicionales. Vea este informe increíblemente completo: https://dba.stackexchange.com/questions/16385/whats-the-difference-between-a-temp-table-and-table-variable-in-sql-server/16386#16386

Aunque hay casos en los que no se puede usar una tabla temporal como en tablas o funciones escalares, para la mayoría de los casos anteriores a v2016 (donde incluso los índices filtrados se pueden agregar a una tabla variable) simplemente puede usar una tabla #temp.

El inconveniente de utilizar índices con nombre (o restricciones) en tempdb es que los nombres pueden entrar en conflicto. No solo teóricamente con otros procedimientos, sino a menudo con bastante facilidad con otras instancias del procedimiento en sí que tratarían de poner el mismo índice en su copia de la tabla #temp.

Para evitar conflictos de nombre, algo como esto normalmente funciona:

declare @cmd varchar(500)='CREATE NONCLUSTERED INDEX [ix_temp'+cast(newid() as varchar(40))+'] ON #temp (NonUniqueIndexNeeded);'; 
exec (@cmd); 

Esto asegura el nombre es siempre único, incluso entre las ejecuciones simultáneas del mismo procedimiento.

+0

Tiene un paréntesis faltante después de varchar (40), agregue que –

+0

No hay problema con los índices con nombre: los índices solo tienen que tener un nombre exclusivo dentro de una tabla. El problema es con las restricciones con nombre y, en general, la mejor solución es no nombrarlas en tablas temporales: las restricciones con nombre previenen el almacenamiento en memoria caché de los objetos de la tabla temporal. –

+0

Eso debe ser cierto solo para ciertas versiones (si es cierto para cualquier versión). Tuve que idear esta solución específicamente porque rastreé las fallas sp hasta el choque de los índices nombrados durante las ejecuciones simultáneas. – bielawski

Cuestiones relacionadas