Encontré una situación extraña en la que agregar OPTION (RECOMPILE)
mi consulta hace que se ejecute en medio segundo, mientras que la omisión hace que la consulta tarde más de cinco minutos.
Este es el caso cuando la consulta se ejecuta desde el Analizador de consultas o desde mi programa C # a través de SqlCommand.ExecuteReader()
. Llamar (o no llamar) DBCC FREEPROCCACHE
o DBCC dropcleanbuffers
no hace ninguna diferencia; Los resultados de la consulta siempre se devuelven instantáneamente con OPTION (RECOMPILE)
y más de cinco minutos sin ella. La consulta siempre se llama con los mismos parámetros [por el bien de esta prueba].
Estoy usando SQL Server 2008.
Me siento bastante cómodo escribiendo SQL, pero nunca antes he usado un OPTION
comando en una consulta y no estaba familiarizado con todo el concepto de cachés de planes hasta escanear las publicaciones en este foro. Mi comprensión de las publicaciones es que OPTION (RECOMPILE)
es una operación costosa. Aparentemente crea una nueva estrategia de búsqueda para la consulta. Entonces, ¿por qué es que las consultas posteriores que omiten OPTION (RECOMPILE)
son tan lentas? ¿No deberían las consultas posteriores hacer uso de la estrategia de búsqueda que se calculó en la llamada anterior que incluía la sugerencia de recompilación?
¿Es muy inusual tener una consulta que requiera una sugerencia de recompilación en cada llamada?
Perdón por la pregunta de nivel de entrada, pero realmente no puedo hacer cara o cruz de esto.
ACTUALIZACIÓN: me han pedido que publique la consulta ...
select acctNo,min(date) earliestDate
from(
select acctNo,tradeDate as date
from datafeed_trans
where feedid=@feedID and feedDate=@feedDate
union
select acctNo,feedDate as date
from datafeed_money
where feedid=@feedID and feedDate=@feedDate
union
select acctNo,feedDate as date
from datafeed_jnl
where feedid=@feedID and feedDate=@feedDate
)t1
group by t1.acctNo
OPTION(RECOMPILE)
Cuando ejecuto la prueba desde el Analizador de consultas, antepongo las siguientes líneas:
declare @feedID int
select @feedID=20
declare @feedDate datetime
select @feedDate='1/2/2009'
Al llamarlo desde mi programa C #, los parámetros se pasan a través de la SqlCommand.Parameters
propiedad.
Para los fines de esta discusión, puede suponer que los parámetros nunca cambian, por lo que podemos descartar el olor de parámetros subóptimos como la causa.
fuente
X = @X OR @X IS NULL
aX=@X
y realizar una buscan vemos aquí o empujar hacia abajo los predicados más contra una vista con las funciones de ventanaRECOMPILE
. En cualquier caso, capture los planes de ejecución y observe las diferencias.Respuestas:
Hay momentos en que usar
OPTION(RECOMPILE)
tiene sentido. En mi experiencia, la única vez que esta es una opción viable es cuando está utilizando SQL dinámico. Antes de explorar si esto tiene sentido en su situación, recomendaría reconstruir sus estadísticas. Esto se puede hacer ejecutando lo siguiente:Y luego recrear su plan de ejecución. Esto asegurará que cuando se cree su plan de ejecución, utilizará la información más reciente.
Agregar
OPTION(RECOMPILE)
reconstruye el plan de ejecución cada vez que se ejecuta su consulta. Nunca he escuchado eso descrito,creates a new lookup strategy
pero tal vez solo estamos usando términos diferentes para la misma cosa.Cuando se crea un procedimiento almacenado (sospecho que está llamando a sql ad-hoc desde .NET, pero si está utilizando una consulta parametrizada, esto termina siendo una llamada de proceso almacenado ) SQL Server intenta determinar el plan de ejecución más efectivo para esta consulta basado en los datos de su base de datos y los parámetros pasados ( análisis de parámetros ), y luego almacena en caché este plan. Esto significa que si crea la consulta donde hay 10 registros en su base de datos y luego la ejecuta cuando hay 100,000,000 registros, el plan de ejecución en caché ya no será el más efectivo.
En resumen: no veo ningún motivo que
OPTION(RECOMPILE)
sea beneficioso aquí. Sospecho que solo necesita actualizar sus estadísticas y su plan de ejecución. La reconstrucción de estadísticas puede ser una parte esencial del trabajo de DBA dependiendo de su situación. Si aún tiene problemas después de actualizar sus estadísticas, sugeriría publicar ambos planes de ejecución.Y para responder a su pregunta, sí, diría que es muy inusual que su mejor opción sea volver a compilar el plan de ejecución cada vez que ejecute la consulta.
fuente
OPTION (RECOMPILE)
podría ser la única solución.A menudo, cuando hay una diferencia drástica de una consulta a otra, encuentro que a menudo es uno de los 5 problemas.
ESTADÍSTICAS- Las estadísticas están desactualizadas. Una base de datos almacena estadísticas sobre el rango y la distribución de los tipos de valores en varias columnas en tablas e índices. Esto ayuda al motor de consulta a desarrollar un "Plan" de ataque sobre cómo realizará la consulta, por ejemplo, el tipo de método que usará para unir claves entre tablas usando un hash o mirando a través de todo el conjunto. Puede llamar a Estadísticas de actualización en toda la base de datos o solo en ciertas tablas o índices. Esto ralentiza la consulta de una ejecución a otra porque cuando las estadísticas están desactualizadas, es probable que el plan de consulta no sea óptimo para los datos recién insertados o modificados para la misma consulta (explicado más adelante). Es posible que no sea adecuado actualizar las estadísticas inmediatamente en una base de datos de producción, ya que habrá algo de sobrecarga, desaceleración y retraso dependiendo de la cantidad de datos a muestrear. También puede optar por utilizar un Análisis completo o Muestreo para actualizar las Estadísticas. Si observa el Plan de consulta, también puede ver las estadísticas de los Índices en uso, como mediante el comandoDBCC SHOW_STATISTICS (nombre de tabla, nombre de índice) . Esto le mostrará la distribución y los rangos de las claves que utiliza el plan de consulta para basar su enfoque.
RASTREO DE PARÁMETROS : el plan de consulta que se almacena en caché no es óptimo para los parámetros particulares que está pasando, a pesar de que la consulta en sí no ha cambiado. Por ejemplo, si pasa un parámetro que solo recupera 10 de 1,000,000 de filas, entonces el plan de consulta creado puede usar un Hash Join, sin embargo, si el parámetro que pasa usará 750,000 de las 1,000,000 filas, el plan creado puede ser un exploración de índice o exploración de tabla. En tal situación, puede decirle a la instrucción SQL que use la opción OPCIÓN (RECOMPILAR) o un SP para usar CON RECOMPILAR. Para decirle al motor que se trata de un "Plan de uso único" y no utilizar un Plan en caché que probablemente no se aplique. No existe una regla sobre cómo tomar esta decisión, depende de saber la forma en que los usuarios utilizarán la consulta.
ÍNDICES : es posible que la consulta no haya cambiado, pero un cambio en otro lugar, como la eliminación de un índice muy útil, ha ralentizado la consulta.
FILAS CAMBIADAS : las filas que está consultando cambian drásticamente de llamada a llamada. Por lo general, las estadísticas se actualizan automáticamente en estos casos. Sin embargo, si está creando SQL dinámico o llamando a SQL dentro de un ciclo cerrado, existe la posibilidad de que esté utilizando un plan de consulta obsoleto basado en el número drástico incorrecto de filas o estadísticas. Nuevamente, en este caso, la OPCIÓN (RECOMPILAR) es útil.
LA LÓGICA Es la lógica, su consulta ya no es eficiente, estaba bien para un pequeño número de filas, pero ya no se escala. Esto generalmente implica un análisis más profundo del Plan de consulta. Por ejemplo, ya no puede hacer cosas a granel, sino que tiene que dividir las cosas y hacer commits más pequeños, o su producto cruzado estaba bien para un conjunto más pequeño pero ahora ocupa CPU y memoria a medida que se amplía, esto también puede ser cierto usando DISTINCT, está llamando a una función para cada fila, sus coincidencias de teclas no usan un índice debido a la conversión de tipo CASTING o NULLS o funciones ... Demasiadas posibilidades aquí.
En general, cuando escribe una consulta, debe tener una idea mental de cómo se distribuyen ciertos datos dentro de su tabla. Una columna, por ejemplo, puede tener un número uniformemente distribuido de valores diferentes, o puede estar sesgada, el 80% del tiempo tiene un conjunto específico de valores, ya sea que la distribución varíe con frecuencia con el tiempo o sea bastante estática. Esto le dará una mejor idea de cómo crear una consulta eficiente. Pero también, al depurar el rendimiento de la consulta, se tiene una base para construir una hipótesis de por qué es lenta o ineficiente.
fuente
Para agregar a la excelente lista (dada por @CodeCowboyOrg) de situaciones en las que OPTION (RECOMPILE) puede ser muy útil,
fuente
Las primeras acciones antes de ajustar las consultas son desfragmentar / reconstruir los índices y las estadísticas, de lo contrario está perdiendo el tiempo.
Debe verificar el plan de ejecución para ver si es estable (es el mismo cuando cambia los parámetros), de lo contrario, es posible que deba crear un índice de cobertura (en este caso para cada tabla) (sabiendo que el sistema puede crear uno que es útil para otras consultas también).
como ejemplo: crear índice idx01_datafeed_trans en datafeed_trans (feedid, feedDate) INCLUDE (acctNo, tradeDate)
si el plan es estable o puede estabilizarlo, puede ejecutar la oración con sp_executesql ('oración SQL') para guardar y usar un plan de ejecución fijo.
si el plan es inestable, debe usar una declaración ad-hoc o EXEC ('oración SQL') para evaluar y crear un plan de ejecución cada vez. (o un procedimiento almacenado "con recompilación").
Espero eso ayude.
fuente
Necroing esta pregunta, pero hay una explicación que nadie parece haber considerado.
ESTADÍSTICAS: las estadísticas no están disponibles o son engañosas
Si todo lo siguiente es cierto:
Entonces, el servidor sql puede estar asumiendo incorrectamente que las columnas no están correlacionadas, lo que lleva a estimaciones de cardinalidad más bajas de lo esperado para aplicar ambas restricciones y un plan de ejecución deficiente seleccionado. La solución en este caso sería crear un objeto de estadísticas que vincule las dos columnas, lo cual no es una operación costosa.
fuente