Crear vistas indizadas
En este tema se describe cómo crear una vista indizada en SQL Server 2012 mediante Transact-SQL. El primer índice creado en una vista debe ser un índice clúster único. Después de haber creado el índice clúster único, puede crear índices no clúster. La creación de un índice clúster único en una vista mejora el rendimiento de la consulta porque la vista se almacena en la base de datos de la misma manera que se almacena una tabla con un índice clúster. El optimizador de consultas puede utilizar vistas indizadas para acelerar la ejecución de las consultas. No es necesario hacer referencia a la vista en la consulta para que el optimizador tenga en cuenta esa vista al hacer una sustitución.
En este tema
Antes de empezar:
Limitaciones y restricciones
Recomendaciones
Consideraciones
Seguridad
Para crear una vista indizada, use:
Transact-SQL
Antes de empezar
Para crear una vista indizada, es necesario seguir los pasos descritos a continuación, que son fundamentales para la correcta implementación de la vista indizada:
Compruebe que las opciones SET sean correctas para todas las tablas existentes a las que se hará referencia en la vista.
Compruebe que las opciones SET de la sesión estén establecidas correctamente antes de crear cualquier tabla nueva y la vista.
Compruebe que la definición de vista sea determinista.
Cree la vista mediante la opción WITH SCHEMABINDING.
Cree el índice clúster único en la vista.
Opciones SET requeridas para vistas indizadas
La evaluación de la misma expresión puede producir resultados diferentes en el Motor de base de datos cuando hay diferentes opciones SET activas cuando se ejecuta la consulta. Por ejemplo, después de establecer la opción SET CONCAT_NULL_YIELDS_NULL en ON, la expresión 'abc' + NULL devuelve el valor NULL. Sin embargo, después de establecer CONCAT_NULL_YIEDS_NULL en OFF, la misma expresión produce 'abc'.
Para asegurar el correcto mantenimiento de las vistas y la generación de resultados coherentes, las vistas indizadas requieren valores fijos para varias opciones SET. Las opciones SET de la tabla siguiente se deben establecer según los valores mostrados en la columna Valor obligatorio cuando se producen las siguientes condiciones:
Se crean la vista y los índices siguientes en la vista.
Las tablas base a las que se hace referencia en la vista cuando se crea la tabla.
Se realiza una operación de inserción, actualización o eliminación en cualquier tabla que participa en la vista indizada. Este requisito incluye operaciones como copia masiva, replicación y consultas distribuidas.
El optimizador de consultas utiliza la vista indizada para producir el plan de consulta.
Opciones SET
Valor requerido
Valor de servidor predeterminado
Valor OLE DB y ODBC
Valor de OLE DB y ODBC
Valor de DB-Library
predeterminado
ANSI_NULLS
ON
ON
ON
OFF
ANSI_PADDING
ON
ON
ON
OFF
ANSI_WARNINGS*
ON
ON
ON
OFF
ARITHABORT
ON
ON
OFF
OFF
CONCAT_NULL_YIELDS_NULL
ON
ON
ON
OFF
NUMERIC_ROUNDABORT
OFF
OFF
OFF
OFF
QUOTED_IDENTIFIER
ON
ON
ON
OFF
*Al establecer ANSI_WARNINGS en ON, ARITHABORT se establece de forma implícita en ON cuando el nivel de compatibilidad de base de datos está establecido en 90 o un valor superior.
Si utiliza una conexión de servidor OLE DB u ODBC, el único valor que se debe modificar es la configuración de ARITHABORT. Todos los valores de DB-Library se deben establecer correctamente en el nivel de servidor mediante sp_configure o desde la aplicación a través del comando SET.
Importante |
---|
Se recomienda encarecidamente que establezca la opción de usuario ARITHABORT en ON en todo el servidor en cuanto se cree la primera vista indizada o el primer índice en una columna calculada en cualquier base de datos del servidor. |
Vistas deterministas
La definición de una vista indizada debe ser determinista. Una vista es determinista si todas las expresiones de la lista de selección y las cláusulas WHERE y GROUP BY son deterministas. Las expresiones deterministas siempre devuelven el mismo resultado cada vez que son evaluadas con un conjunto específico de valores de entrada. Solo las funciones deterministas pueden participar en expresiones deterministas. Por ejemplo, la función DATEADD es determinista porque siempre devuelve el mismo resultado para cualquier conjunto dado de valores de argumento para sus tres parámetros. GETDATE no es determinista porque siempre se invoca con el mismo argumento, pero el valor que devuelve varía cada vez que se ejecuta.
Para determinar si una columna de la vista es determinista, use la propiedad IsDeterministic de la función COLUMNPROPERTY. Para determinar si una columna determinista de una vista con enlace de esquema es precisa, use la propiedad IsPrecise de la función COLUMNPROPERTY. COLUMNPROPERTY devuelve 1 si es TRUE, 0 si es FALSE y NULL si la entrada no es válida. Esto significa que la columna no es determinista ni precisa.
Aun cuando una expresión sea determinista, si contiene expresiones de tipo float, es posible que un resultado exacto dependa de la arquitectura de procesador o de la versión de microcódigo. Para asegurar la integridad de los datos, estas expresiones solo pueden participar como columnas que no son de clave de vistas indizadas. Las expresiones deterministas que no contienen expresiones flotantes se denominan expresiones precisas. Solo las expresiones deterministas precisas pueden participar en columnas de clave y en cláusulas WHERE o GROUP BY de vistas indizadas.
[Arriba]
Requisitos adicionales
Además de las opciones SET y los requisitos de funciones deterministas, se deben cumplir los requisitos siguientes:
El usuario que ejecuta CREATE INDEX debe ser el propietario de la vista.
Cuando crea el índice, la opción IGNORE_DUP_KEY debe establecerse en OFF (configuración predeterminada).
En la definición de vista, se debe hacer referencia a las tablas mediante nombres de dos partes, schema**.**tablename.
Las funciones definidas por el usuario a las que se hace referencia en la vista se deben crear con la opción WITH SCHEMABINDING.
Para hacer referencia a las funciones definidas por el usuario a las que se hace referencia en la vista se deben usar nombres de dos partes, schema**.**function.
La propiedad de acceso a datos de una función definida por el usuario debe ser NO SQL y la propiedad de acceso externo debe ser NO.
Las funciones de Common Language Runtime (CLR) pueden aparecer en la lista de selección de la vista, pero no pueden formar parte de la definición de la clave de índice clúster. Las funciones CLR no pueden aparecer en la cláusula WHERE de la vista ni en la cláusula ON de una operación JOIN en la vista.
Los métodos y las funciones CLR de tipos definidos por el usuario CLR utilizados en la definición de la vista deben establecer las propiedades según se indica en la tabla siguiente.
Propiedad
Nota
DETERMINISTIC = TRUE
Debe declararse de forma explícita como un atributo del método de Microsoft .NET Framework.
PRECISE = TRUE
Debe declararse de forma explícita como un atributo del método de .NET Framework.
DATA ACCESS = NO SQL
Se determina mediante la definición del atributo DataAccess como DataAccessKind.None y del atributo SystemDataAccess como SystemDataAccessKind.None.
EXTERNAL ACCESS = NO
Esta propiedad tiene el valor predeterminado NO en rutinas CLR.
Esta vista se debe crear utilizando la opción WITH SCHEMABINDING.
La vista solo debe hacer referencia a tablas base que estén en la misma base de datos que la vista. La vista no puede hacer referencia a otras vistas.
La instrucción SELECT de la definición de vista no debe contener los siguientes elementos de Transact-SQL:
COUNT
Funciones ROWSET (OPENDATASOURCE, OPENQUERY, OPENROWSET y OPENXML)
Combinaciones externas (LEFT, RIGHT o FULL)
Tabla derivada (definida mediante una instrucción SELECT en la cláusula FROM)
Autocombinaciones
Especificar columnas mediante SELECT * o SELECT nombre_tabla.*
DISTINCT
STDEV, STDEVP, VAR, VARP o AVG
Expresión de tabla común (CTE)
Columnas float*, text, ntext, image, XML o filestream
Subconsulta
Cláusula OVER, que incluye funciones de categoría o de agregado
Predicados de texto completo (CONTAIN, FREETEXT)
Función SUM que hace referencia a una expresión que acepta valores NULL
ORDER BY
Función de agregado definida por el usuario CLR
TOP
Operadores CUBE, ROLLUP o GROUPING SETS
MIN, MAX
Operadores UNION, EXCEPT o INTERSECT
TABLESAMPLE
Variables de tabla
OUTER APPLY o CROSS APPLY
PIVOT, UNPIVOT
Conjuntos de columnas dispersas
Funciones insertadas o con valores de tabla de múltiples instrucciones
OFFSET
CHECKSUM_AGG
*La vista indizada puede contener columnas float; sin embargo, esas columnas no se pueden incluir en la clave de índice clúster.
Si GROUP BY está presente, la definición de VIEW debe contener COUNT_BIG(*) y no debe contener HAVING. Estas restricciones GROUP BY solo se pueden aplicar a la definición de vista indizada. Una consulta puede utilizar una vista indizada en su plan de ejecución aun cuando no satisfaga estas restricciones GROUP BY.
Si la definición de vista contiene una cláusula GROUP BY, la clave del índice clúster único solo puede hacer referencia a las columnas especificadas en esta cláusula.
Recomendaciones
Cuando haga referencia a los literales de cadena datetime y smalldatetime de las vistas indizadas, se recomienda convertir explícitamente el literal al tipo de datos deseado mediante un estilo de formato de fecha determinista. Para consultar una lista de los estilos de formato de fecha deterministas, vea CAST y CONVERT (Transact-SQL). Las expresiones que implican la conversión implícita de cadenas de caracteres a datetime o smalldatetime se consideran no deterministas. Esto se debe a que los resultados dependen de los valores LANGUAGE y DATEFORMAT de la sesión de servidor. Por ejemplo, los resultados de la expresión CONVERT (datetime, '30 listopad 1996', 113) dependen del valor de LANGUAGE porque la cadena 'listopad' significa distintos meses en distintos idiomas. De forma similar, en la expresión DATEADD(mm,3,'2000-12-01'), SQL Server interpretará la cadena '2000-12-01' en función del valor de DATEFORMAT.
La conversión implícita de los datos de caracteres no Unicode entre intercalaciones también se considera no determinista.
No se permite crear índices en las vistas que contienen estas expresiones de conversión implícita en el nivel de compatibilidad 90 y superiores. Sin embargo, las vistas existentes que contienen estas expresiones procedentes de una base de datos actualizada se pueden mantener. Si utiliza vistas indizadas que contienen conversiones implícitas de cadena a fecha, asegúrese de que las opciones LANGUAGE y DATEFORMAT son coherentes en las bases de datos y las aplicaciones, para evitar posibles daños en las vistas indizadas.
Consideraciones
El valor de la opción large_value_types_out_of_row en las columnas de una vista indizada se hereda de la configuración de la columna correspondiente en la tabla base. Este valor se establece con sp_tableoption. La configuración predeterminada de las columnas formadas a partir de expresiones es 0. Esto significa que los tipos de valores grandes se almacenan de forma consecutiva.
En una tabla con particiones se pueden crear vistas indizadas, en las que a su vez se pueden crear particiones.
Para evitar que el Motor de base de datos use vistas indizadas, incluya la sugerencia OPTION (EXPAND VIEWS) en la consulta. Además, si alguna de las opciones enumeradas no está establecida correctamente, el optimizador no utilizará los índices en las vistas. Para obtener más información sobre la sugerencia OPTION (EXPAND VIEWS), vea SELECT (Transact-SQL).
Si se quita la vista, todos sus índices se quitan. Todos los índices no clúster y las estadísticas creadas automáticamente de una vista se quitan si se quita el índice clúster. Las estadísticas creadas por el usuario de la vista se conservan. Los índices no clúster se pueden quitar individualmente. Quitar el índice clúster de la vista quita el conjunto de resultados almacenado; el optimizador vuelve a procesar la vista como una vista estándar.
Los índices de las tablas y las vistas se pueden deshabilitar. Cuando se deshabilita un índice clúster de una tabla, también se deshabilitan los índices de las vistas asociadas a la tabla.
[Arriba]
Seguridad
Permisos
Se necesita el permiso CREATE VIEW en la base de datos y el permiso ALTER en el esquema en que se crea la vista.
[Arriba]
Usar Transact-SQL
Para crear una vista indizada
En el Explorador de objetos, conéctese a una instancia del Motor de base de datos.
En la barra de Estándar, haga clic en Nueva consulta.
Copie y pegue el siguiente ejemplo en la ventana de consulta y haga clic en Ejecutar. El ejemplo crea una vista y un índice en esa vista. Se incluyen dos consultas que utilizan la vista indizada.
USE AdventureWorks2012; GO --Set the options to support indexed views. SET NUMERIC_ROUNDABORT OFF; SET ANSI_PADDING, ANSI_WARNINGS, CONCAT_NULL_YIELDS_NULL, ARITHABORT, QUOTED_IDENTIFIER, ANSI_NULLS ON; GO --Create view with schemabinding. IF OBJECT_ID ('Sales.vOrders', 'view') IS NOT NULL DROP VIEW Sales.vOrders ; GO CREATE VIEW Sales.vOrders WITH SCHEMABINDING AS SELECT SUM(UnitPrice*OrderQty*(1.00-UnitPriceDiscount)) AS Revenue, OrderDate, ProductID, COUNT_BIG(*) AS COUNT FROM Sales.SalesOrderDetail AS od, Sales.SalesOrderHeader AS o WHERE od.SalesOrderID = o.SalesOrderID GROUP BY OrderDate, ProductID; GO --Create an index on the view. CREATE UNIQUE CLUSTERED INDEX IDX_V1 ON Sales.vOrders (OrderDate, ProductID); GO --This query can use the indexed view even though the view is --not specified in the FROM clause. SELECT SUM(UnitPrice*OrderQty*(1.00-UnitPriceDiscount)) AS Rev, OrderDate, ProductID FROM Sales.SalesOrderDetail AS od JOIN Sales.SalesOrderHeader AS o ON od.SalesOrderID=o.SalesOrderID AND ProductID BETWEEN 700 and 800 AND OrderDate >= CONVERT(datetime,'05/01/2002',101) GROUP BY OrderDate, ProductID ORDER BY Rev DESC; GO --This query can use the above indexed view. SELECT OrderDate, SUM(UnitPrice*OrderQty*(1.00-UnitPriceDiscount)) AS Rev FROM Sales.SalesOrderDetail AS od JOIN Sales.SalesOrderHeader AS o ON od.SalesOrderID=o.SalesOrderID AND DATEPART(mm,OrderDate)= 3 AND DATEPART(yy,OrderDate) = 2002 GROUP BY OrderDate ORDER BY OrderDate ASC; GO
Para obtener más información, vea CREATE VIEW (Transact-SQL).
[Arriba]
Vea también
Referencia
SET ANSI_PADDING (Transact-SQL)
SET ANSI_WARNINGS (Transact-SQL)
SET CONCAT_NULL_YIELDS_NULL (Transact-SQL)