Eventos
31 mar, 23 - 2 abr, 23
Evento de aprendizaje de SQL, Fabric y Power BI más grande. 31 de marzo – 2 de abril. Use el código FABINSIDER para ahorrar $400.
Regístrate hoyEste explorador ya no se admite.
Actualice a Microsoft Edge para aprovechar las características y actualizaciones de seguridad más recientes, y disponer de soporte técnico.
Se aplica a: SQL Server
Azure SQL Database
Azure SQL Managed Instance
En este artículo se describe cómo crear índices en una vista. 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 más índices no clúster. La creación de un índice clúster único en una vista mejora el rendimiento de las consultas, ya que la vista se almacena en la base de datos de la misma manera que se almacena una tabla con un índice agrupado. 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 para una sustitución.
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:
SET
son correctas para todas las tablas existentes a las que se hará referencia en la vista.SET
de la sesión estén establecidas correctamente antes de crear cualquier tabla y la vista.WITH SCHEMABINDING
.Al ejecutar operaciones UPDATE
, DELETE
o INSERT
(lenguaje de manipulación de datos o DML) en una tabla a la que hace referencia un gran número de vistas indexadas, o menos vistas indexadas complejas, esas vistas indizadas a las que se hace referencia también tienen que actualizarse. Como resultado, el rendimiento de la consulta DML se puede degradar notablemente o, en algunos casos, puede que tampoco se genere un plan de consulta.
En estos casos, pruebe las consultas DML antes de usarlas en entornos de producción, analice el plan de consulta y ajuste o simplifique la instrucción DML.
La evaluación de la misma expresión puede generar resultados diferentes en el motor de base de datos cuando hay distintas 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, al establecer CONCAT_NULL_YIELDS_NULL
en OFF
, la misma expresión genera 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 deben establecerse en los valores que se muestran en la columna Required value
siempre que se produzcan las condiciones siguientes:
Opciones de Set | Valor requerido | Valor de servidor predeterminado | Valor predeterminado Valor de OLE DB y ODBC |
Valor predeterminado predeterminado |
---|---|---|---|---|
ANSI_NULLS |
ON |
ON |
ON |
OFF |
ANSI_PADDING |
ON |
ON |
ON |
OFF |
ANSI_WARNINGS 1 |
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 |
1 Si se establece ANSI_WARNINGS
en ON
, ARITHABORT
se establece implícitamente en ON
.
Si usa 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 deben establecerse correctamente en el nivel de servidor mediante sp_configure
o desde la aplicación mediante el comando SET
.
Importante
Se recomienda encarecidamente establecer la opción de usuario en ARITHABORT
todo el servidor ON
en cuanto se cree la primera vista indizada o índice en una columna calculada en cualquier base de datos del servidor.
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 se evalúan 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 cambia cada vez que se ejecuta.
Para determinar si una columna de vista es determinista, use la propiedad IsDeterministic
de la función COLUMNPROPERTY. Para determinar si una columna determinista en una vista con enlace de esquema es precisa, use la propiedad IsPrecise
de la función COLUMNPROPERTY
. COLUMNPROPERTY
devuelve 1
si TRUE
, 0
si FALSE
y NULL
para la entrada que no es válida. Esto significa que la columna no es determinista o no es 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 float se denominan precisas. Solo las expresiones deterministas precisas pueden participar en columnas de clave y en cláusulas WHERE
o GROUP BY
de vistas indizadas.
También se deben cumplir los siguientes requisitos, además de las opciones SET
y los requisitos de función deterministas.
El usuario que ejecuta CREATE INDEX
debe ser el propietario de la vista.
Al crear el índice, la opción de índice IGNORE_DUP_KEY
debe establecerse en OFF
(la 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 agrupada. Las funciones CLR no pueden aparecer en la cláusula WHERE
de la vista o 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 | Determinado estableciendo el atributo DataAccess en DataAccessKind.None y el atributo SystemDataAccess en SystemDataAccessKind.None . |
EXTERNAL ACCESS = NO | Esta propiedad tiene el valor predeterminado NO en rutinas CLR. |
La vista se debe crear mediante 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.
Si GROUP BY
está presente, la definición de VIEW debe contener COUNT_BIG(*)
, pero no HAVING
. Estas restricciones GROUP BY
solo se pueden aplicar a la definición de vista indizada. Una consulta puede usar una vista indizada en su plan de ejecución aunque no cumpla 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 la cláusula GROUP BY
.
La instrucción SELECT
de la definición de vista no debe contener la siguiente sintaxis de Transact-SQL:
Función de Transact-SQL | Posibles alternativas |
---|---|
COUNT |
Use COUNT_BIG |
Funciones ROWSET (OPENDATASOURCE , OPENQUERY , OPENROWSET y OPENXML ) |
|
Media aritmética (AVG ) |
Usar COUNT_BIG y SUM como columnas independientes |
Funciones de agregado estadístico (STDEV , STDEVP , VAR y VARP ) |
|
Función SUM que hace referencia a una expresión que acepta valores NULL |
Usar ISNULL dentro de SUM() para que la expresión no acepte valores NULL |
Otras funciones de agregado (MIN , MAX , CHECKSUM_AGG y STRING_AGG ) |
|
Funciones de agregado definidas por el usuario (SQL CLR) |
Cláusula SELECT | Elemento de Transact-SQL | Posible alternativa |
---|---|---|
WITH cte AS |
Expresiones de tabla comunes (CTE) WITH |
|
SELECT |
Subconsultas | |
SELECT |
SELECT [ <table>. ] * |
Asignar nombre a las columnas explícitamente |
SELECT |
SELECT DISTINCT |
Use GROUP BY |
SELECT |
SELECT TOP |
|
SELECT |
Cláusula OVER , que incluye funciones de categoría o de agregado |
|
FROM |
LEFT OUTER JOIN |
|
FROM |
RIGHT OUTER JOIN |
|
FROM |
FULL OUTER JOIN |
|
FROM |
OUTER APPLY |
|
FROM |
CROSS APPLY |
|
FROM |
Expresiones de tabla derivadas (es decir, mediante SELECT en la cláusula FROM ) |
|
FROM |
Autocombinaciones | |
FROM |
Variables de tabla | |
FROM |
Función insertada con valores de tabla | |
FROM |
Función con valores de tabla de varias instrucciones | |
FROM |
PIVOT , UNPIVOT |
|
FROM |
TABLESAMPLE |
|
FROM |
FOR SYSTEM_TIME |
Consulta directamente de la tabla de historial temporal |
WHERE |
Predicados de texto completo (CONTAINS , FREETEXT , CONTAINSTABLE , FREETEXTTABLE ) |
|
GROUP BY |
Operadores CUBE , ROLLUP o GROUPING SETS |
Definir vistas indizadas independientes para cada combinación de columnas GROUP BY |
GROUP BY |
HAVING |
|
Operadores de conjuntos | UNION , UNION ALL , EXCEPT , INTERSECT |
Use OR , AND NOT y AND en la cláusula WHERE respectivamente. |
ORDER BY |
ORDER BY |
|
ORDER BY |
OFFSET |
Tipo de columna de origen | Posible alternativa |
---|---|
Tipos de columna de valores grandes en desuso (text, ntext e image) | Migre columnas a varchar(max), nvarchar(max) y varbinary(max) respectivamente. |
columnas xml o FILESTREAM | |
float 1 columnas en la clave de índice | |
Conjuntos de columnas dispersas |
1 La vista indizada puede contener columnas float; sin embargo, estas columnas no se pueden incluir en la clave de índice agrupada.
Importante
No se admiten vistas indexadas con consultas temporales (las consultas que usan la cláusula FOR SYSTEM_TIME
).
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 obtener una lista de los estilos de formato de fecha deterministas, vea CAST y CONVERT. Para obtener más información sobre las expresiones deterministas y no deterministas, consulte la sección Consideraciones de esta página.
Las expresiones que implican la conversión implícita de cadenas de caracteres a datetime o smalldatetime se consideran no deterministas. Para obtener más información, vea Conversión no determinista de las cadenas de fecha literales en valores DATE.
Al ejecutar DML (como UPDATE
, DELETE
o INSERT
) en una tabla a la que hace referencia un gran número de vistas indizadas, o menos vistas indizadas complejas, esas vistas indizadas tienen que actualizarse también durante la ejecución de DML. Como resultado, el rendimiento de la consulta DML se puede degradar notablemente o, en algunos casos, puede que tampoco se genere un plan de consulta. En estos casos, pruebe las consultas DML antes de usarlas en entornos de producción, analice el plan de consulta y ajuste o simplifique la instrucción DML.
Para evitar que el use vistas indizadas, incluya la sugerencia OPTION (EXPAND VIEWS) en la consulta. Además, si alguna de las opciones enumeradas no está establecida correctamente, esta opción impide que el optimizador utilice los índices en las vistas. Para obtener más información sobre la sugerencia OPTION (EXPAND VIEWS)
, consulte SELECT.
La configuración de la opción large_value_types_out_of_row
de las columnas de una vista indexada se hereda de la configuración de la columna correspondiente de la tabla base. Este valor se establece mediante 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.
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.
Para crear la vista, un usuario necesita el permiso CREATE VIEW
en la base de datos y el permiso ALTER
en el esquema en el que se crea la vista. Si la tabla base reside en otro esquema, por lo menos se requiere el permiso REFERENCES
relativo a la tabla. Si el usuario que crea el índice difiere de los usuarios que crearon la vista, para la creación del índice solo se requiere el permiso ALTER
en la vista (cubierto por ALTER
en el esquema).
Los índices solo se pueden crear en vistas que tengan el mismo propietario que la tabla o las tablas a las que se hace referencia. Este concepto también se denomina cadena de propiedad intacta entre la vista y las tablas. Normalmente, cuando la tabla y la vista residen en el mismo esquema, el mismo propietario del esquema se aplica a todos los objetos del esquema. Por lo tanto, es posible crear una vista y no ser el propietario de la vista. Por otro lado, también es posible que objetos concretos de un esquema tengan propietarios explícitos diferentes. La columna principal_id
de sys.tables
contiene un valor si el propietario es diferente del propietario del esquema.
En el ejemplo siguiente se crea una vista y un índice en esa vista, en la base de datos AdventureWorks
.
--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;
--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
Las dos consultas siguientes muestran cómo se puede usar la vista indizada, aunque la vista no se especifique en la cláusula FROM
.
--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
INNER JOIN Sales.SalesOrderHeader AS o
ON od.SalesOrderID = o.SalesOrderID
AND o.OrderDate >= CONVERT(DATETIME, '05/01/2012', 101)
WHERE od.ProductID BETWEEN 700
AND 800
GROUP BY OrderDate,
ProductID
ORDER BY Rev DESC;
GO
--This query will also use the above indexed view.
SELECT OrderDate,
SUM(UnitPrice * OrderQty * (1.00 - UnitPriceDiscount)) AS Rev
FROM Sales.SalesOrderDetail AS od
INNER JOIN Sales.SalesOrderHeader AS o
ON od.SalesOrderID = o.SalesOrderID
AND o.OrderDate >= CONVERT(DATETIME, '03/01/2012', 101)
AND o.OrderDate < CONVERT(DATETIME, '04/01/2012', 101)
GROUP BY OrderDate
ORDER BY OrderDate ASC;
Por último, en este ejemplo se muestra la consulta directamente desde la vista indizada. Antes de SQL Server 2016 (13.x) Service Pack 1, el uso automático de una vista indexada por parte del optimizador de consultas solo se admite en determinadas ediciones de SQL Server. En la edición SQL Server Standard, debe usar la sugerencia de consulta NOEXPAND
para consultar la vista indizada directamente. Desde SQL Server 2016 (13.x) Service Pack 1, todas las ediciones admiten el uso automático de una vista indizada. La base de datos de Azure SQL y Azure SQL Managed Instance también admiten el uso automático de vistas indexadas sin especificar la sugerencia NOEXPAND
. Para obtener más información, vea Sugerencias de tabla (Transact-SQL).
--This query uses the indexed view directly, on Enterprise edition.
SELECT OrderDate, Revenue
FROM Sales.vOrders
WHERE OrderDate >= CONVERT(DATETIME, '03/01/2012', 101)
AND OrderDate < CONVERT(DATETIME, '04/01/2012', 101)
ORDER BY OrderDate ASC;
--This query uses the indexed view directly, with the NOEXPAND hint.
SELECT OrderDate, Revenue
FROM Sales.vOrders WITH (NOEXPAND)
WHERE OrderDate >= CONVERT(DATETIME, '03/01/2012', 101)
AND OrderDate < CONVERT(DATETIME, '04/01/2012', 101)
ORDER BY OrderDate ASC;
Para más información, consulte CREATE VIEW.
Eventos
31 mar, 23 - 2 abr, 23
Evento de aprendizaje de SQL, Fabric y Power BI más grande. 31 de marzo – 2 de abril. Use el código FABINSIDER para ahorrar $400.
Regístrate hoyCursos
Módulo
Creación de tablas, vistas y objetos temporales - Training
Este contenido forma parte de Creación de tablas, vistas y objetos temporales.
Documentación
CREATE MATERIALIZED VIEW AS SELECT (Transact-SQL)
CREATE INDEX (Transact-SQL) - SQL Server
CREATE INDEX (Transact-SQL)
Crear índices con columnas incluidas - SQL Server
Crear índices con columnas incluidas