Sus preguntas están por todas partes, así que trataré de abordarlas todas. El caché de procedimiento es solo tan grande. Es posible que su caché de procedimientos se haya rellenado con planes de un solo uso (esto no tiene ningún impacto en las estadísticas, aunque las estadísticas pueden afectar el caché del plan). Puede leer muchos detalles sobre los planes de un solo uso en la publicación de blog de Kimberly Tripp, "Plan cache and optimizing for adhoc workloads", incluida una consulta en contra del sys.dm_exec_cached_plans que ayudará a identificar cuándo se llena el caché con muchos planes de un solo uso. Como ella sugiere, puede evitar esta hinchazón utilizando optimizar para cargas de trabajo ad hoc. Si encuentra la necesidad de hacer esto a menudo, diría que programar freeproccache como trabajo es una curita, no una solución.
Para eliminar un plan "malo", primero debe identificar el plan "malo". Puede tratarse de un plan que excede un determinado tamaño y/o no se ha ejecutado en algún momento, o que ha identificado mediante una consulta de larga ejecución, etc. Desafortunadamente no es sencillo identificar un plan que es víctima de un parámetro olfatear a menos que ya sepas la consulta o las consultas que se ven afectadas. Supongamos que usted quiere encontrar los planes más antiguos de la memoria caché que no ha sido dirigido en más de una semana:
;WITH x AS
(
SELECT TOP 10
qs.[sql_handle], qs.plan_handle,
txs = qs.statement_start_offset,
txe = qs.statement_end_offset,
[size] = cp.size_in_bytes,
[uses] = SUM(cp.usecounts),
[last] = MAX(qs.last_execution_time)
FROM
sys.dm_exec_query_stats AS qs
INNER JOIN
sys.dm_exec_cached_plans AS cp
ON qs.plan_handle = cp.plan_handle
WHERE
qs.last_execution_time < DATEADD(DAY, -7, CURRENT_TIMESTAMP)
GROUP BY
qs.[sql_handle], qs.plan_handle, cp.size_in_bytes,
qs.statement_start_offset, qs.statement_end_offset
ORDER BY
[size] DESC
)
SELECT
x.plan_handle,
size, uses, [last],
[statement] = COALESCE(NULLIF(
SUBSTRING(t.[text], x.txs/2,
CASE WHEN x.txe = -1 THEN 0 ELSE (x.txe - x.txs)/2 END
), ''), t.[text])
FROM x
CROSS APPLY sys.dm_exec_sql_text(x.[sql_handle]) AS t;
Ahora tiene que verificar que realmente desea borrar a cabo este plan. Por ejemplo, si reconoce esa consulta como algo que el CEO podría ejecutar mañana, tal vez sea mejor dejarla allí. Si desea borrar el plan, puede borrar directamente diciendo:
DBCC FREEPROCCACHE([paste plan handle from above query here]);
Esto suena como mucho más trabajo que ejecuta DBCC FREEPROCCACHE
a nivel mundial, pero si usted tiene una gran cantidad de buenas planes en la memoria caché, sin duda va a ser mejor para sus usuarios en general.
Aún así, esto realmente suena como una curita. Si su caché se está llenando de basura y el rendimiento va al baño hasta que libere la caché, debe buscar un nivel superior en la arquitectura, cómo se envían las consultas, etc. Este es el comportamiento que esperaría del primera iteración de LINQ2SQL, donde almacenaba en caché una versión de un plan para una consulta para cada argumento de cadena que tenía una longitud diferente. Entonces, si tuviera un parámetro de 'Enero', obtendría un plan diferente que con un parámetro de 'Febrero' porque definiría el tipo de datos como VARCHAR(7)
frente a VARCHAR(8)
. Estoy bastante seguro de que el comportamiento es fijo, pero no sé lo suficiente sobre su entorno/aplicación para sugerir dónde buscar precisamente las "malas ideas".
Identifique qué versión de SQL Server está utilizando, p. Ej. [tag: sql-server-2005], [tag: sql-server-2008] ... –
Todo 'DBCC freeproccache' hace vaciar el caché del procedimiento. No hará que las estadísticas se actualicen. Por el contrario, si las estadísticas se actualizan automáticamente, el plan se volverá a compilar.Supongo que tiene un problema de detección de parámetros donde el plan que estaba en el caché para una consulta no era adecuado para todos los posibles valores de parámetros. –
¡Estoy en SQL Server 2005! – user173552