¿Sería mejor dividir los planes de consulta por declaración para volver a usarlos?

11

Según mi conocimiento limitado de cómo se compilan, almacenan y recuperan los planes de consulta mediante consultas, entiendo que una consulta de varios estados o un procedimiento almacenado generará su plan de consulta que se almacenará en la caché del plan de consulta para que la consulta la use en futuras ejecuciones.

Creo que este plan se recupera de la memoria caché del plan de consulta con el hash de consulta, lo que significa que si la consulta se edita y ejecuta, el hash es diferente y se genera un nuevo plan ya que no se puede encontrar un hash coincidente en la memoria caché del plan de consulta.

Mi pregunta es: si un usuario ejecuta una declaración que es una de las declaraciones en la consulta de varias declaraciones, ¿puede usar esa parte relevante del plan de consulta que ya está en el caché para la consulta de varias declaraciones? Espero que la respuesta sea no porque los valores hash obviamente no coincidirán, pero ¿sería mejor hacer hash cada declaración en una consulta de múltiples declaraciones para que puedan ser utilizados por los usuarios que ejecutan declaraciones individuales de la consulta?

Espero que haya complicaciones que no estoy teniendo en cuenta (y es esto de lo que realmente quiero saber), pero parece que podríamos estar almacenando el mismo 'plan de estado de cuenta' en muchos planes de consulta que ocupan más espacio y ocupan más CPU y tiempo para generar.

Sin embargo, podría estar mostrando mi ignorancia.

James Anderson
fuente
dbidy objectidambos lo tienen is_cache_key=1para que no pueda reutilizar los planes entre diferentes objetos compilados.
Martin Smith

Respuestas:

11

Si un usuario ejecuta una declaración que es una de las declaraciones en la consulta de varias declaraciones, ¿puede usar esa parte relevante del plan de consulta que ya está en la caché para la consulta de varias declaraciones?

No. La unidad básica de reutilización del plan en SQL Server es el lote .

¿Sería mejor hacer un hash de cada declaración en una consulta de varias declaraciones para que puedan ser utilizados por los usuarios que ejecutan declaraciones individuales de la consulta?

Un sistema ajustado para altos niveles de reutilización del plan colocará código común (con una granularidad adecuada) en objetos reutilizables (por ejemplo, procedimientos, funciones, disparadores) en el servidor SQL. También parametrizará explícitamente cualquier código generado por la aplicación o del lado del cliente. Para una reutilización máxima del plan, estos lotes generados deberían diferir solo en los valores de los parámetros.

Espero que haya complicaciones que no estoy teniendo en cuenta.

Parece que se pregunta por qué SQL Server fue diseñado para almacenar en caché y reutilizar a nivel de lote, en lugar de a nivel de declaración. Dudo que alguien aparte de los diseñadores originales pueda responder esta pregunta con autoridad. De todos modos, me parece que un lote es una granularidad natural de usar porque es una unidad de trabajo natural relativamente autónoma y representa una compensación razonable entre la complejidad de la implementación y la probabilidad de reutilización del plan.

Hay algunas cosas que hacen que los lotes no sean completamente autónomos (por ejemplo, tablas temporales locales creadas y referenciadas a través de límites de procedimientos almacenados). Estas excepciones reducen la ortogonalidad y se han asociado con comportamientos y errores inesperados 'por diseño' a lo largo de los años.

Paul White 9
fuente