sql >> Base de Datos >  >> RDS >> Sqlserver

¿Cuáles son las principales diferencias entre OPCIÓN (OPTIMIZAR PARA DESCONOCIDO) y OPCIÓN (RECOMPILAR)?

Sí, lo hará.

Hay dos diferencias principales entre OPTION(OPTIMIZE FOR UNKNOWN) y OPTION(RECOMPILE) como se puede ver en esta cita de MSDN :

Entonces, las dos diferencias principales son:

  1. Almacenamiento en caché (o no) del plan de consulta.

Por lo general, el plan de consulta generado se almacena en caché y se reutiliza. OPTIMIZE FOR UNKNOWN no afecta esta función del motor. RECOMPILE suprime esta característica y le dice al motor que descarte el plan y no lo guarde en el caché.

  1. Usar (o no) valores de parámetros reales durante la generación del plan.

Por lo general, el optimizador "olfatea" los valores de los parámetros y utiliza estos valores al generar el plan. OPTIMIZE FOR UNKNOWN suprime esta característica y le dice al motor que trate todos los parámetros como si sus valores fueran desconocidos. Optimizer tiene reglas y heurísticas incorporadas sobre cómo usar las estadísticas disponibles para varios criterios de filtrado. Consulte Optimizar para... ¿Mediocre? para más detalles. Normalmente, la detección de parámetros se usa en la primera ejecución de la consulta/procedimiento almacenado y usa los valores de los parámetros durante la primera ejecución. El plan generado se almacena en caché y luego se puede reutilizar.

Una cosa que no es obvia para recordar aquí es que en ambos casos (normal sin sugerencias de consulta y con OPTIMIZE FOR UNKNOWN pista) el plan generado tiene que ser válido y producir el resultado correcto para cualquier posible valor del parámetro. Se adapta a los valores rastreados que se usaron durante la primera ejecución en el caso normal/sin pistas; no se adapta a ningún valor específico en OPTIMIZE FOR UNKNOWN caso, pero sigue siendo válido si el parámetro cambia más tarde de alguna manera.

Esto es significativo y evita que el optimizador realice ciertas transformaciones y simplificaciones del plan.

OPTION(RECOMPILE) permite al optimizador alinear los valores reales de los parámetros durante cada ejecución y el optimizador usa los valores reales de los parámetros para generar un mejor plan. No tiene que preocuparse de que el plan generado no funcione con algún otro valor de parámetro, porque el plan no se almacenará en caché ni se reutilizará.

Este efecto es principalmente visible para las Condiciones de búsqueda dinámica consultas Por ejemplo:

SELECT ...
FROM T
WHERE
    (@ParamSomeID = 0)
    OR
    (
        @ParamSomeID = -1
        AND
        T.SomeID NOT IN
        (
            SELECT OtherTable.SomeID
            FROM OtherTable
        )
    )
    OR
    (
        T.SomeID IN
        (
            SELECT OtherTable.SomeID
            FROM OtherTable
            WHERE OtherTable.SomeID = @ParamSomeID
        )
    )
OPTION(RECOMPILE)

Si @ParamSomeID es 0 el optimizador trataría la consulta como si no tuviera ningún WHERE cláusula en absoluto. El plan no mencionaría OtherTable en absoluto.

Si @ParamSomeID es -1 , el plan se uniría a T a OtherTable usando Left Anti Semi Join y escanearía toda la OtherTable .

Si @ParamSomeID es, digamos, 5, el plan haría una búsqueda de índice en un índice único en OtherTable y lea solo una fila de OtherTable .

Sin OPTION(RECOMPILE) este tipo de simplificación y transformación no ocurriría.

Otra razón para usar OPTION(RECOMPILE) es cuando su distribución de datos es muy sesgada. Por ejemplo, tiene una tabla con 1M de filas. Una columna tiene valor 0 en 990K filas y valores del 1 al 10 en 1K filas. Las consultas que filtran en esta columna deben tener diferentes planes según el valor real del filtro.

En los dos ejemplos anteriores OPTIMIZE FOR UNKNOWN generaría un plan mediocre.