Para una consulta moderadamente compleja que estoy tratando de optimizar, noté que eliminar la TOP n
cláusula cambia el plan de ejecución. Habría adivinado que cuando una consulta incluye TOP n
el motor de la base de datos, se ejecutaría la consulta ignorando la TOP
cláusula, y luego, al final, simplemente reduciría el resultado establecido a la n cantidad de filas que se solicitó. El plan de ejecución gráfico parece indicar que este es el caso, TOP
es el "último" paso. Pero parece que están sucediendo más.
Mi pregunta es, ¿cómo (y por qué) una cláusula TOP n impacta el plan de ejecución de una consulta?
Aquí hay una versión simplificada de lo que está sucediendo en mi caso:
La consulta coincide con filas de dos tablas, A y B.
Sin la TOP
cláusula, el optimizador estima que habrá 19k filas de la tabla A y 46k filas de la tabla B. El número real de filas devueltas es 16k para A y 13k para B. Se utiliza una coincidencia hash para unir estos dos conjuntos de resultados para un total de 69 filas (luego se aplica una ordenación). Esta consulta ocurre muy rápidamente.
Cuando agrego TOP 1001
el optimizador no utiliza una coincidencia hash; en su lugar, primero ordena los resultados de la tabla A (la misma estimación / real de 19k / 16k) y realiza un bucle anidado contra la tabla B. El número estimado de filas para la tabla B ahora es 1, y lo extraño es que TOP n
afecta directamente número estimado de ejecuciones (búsqueda de índice) contra B: parece ser siempre 2n + 1 , o en mi caso 2003. Esta estimación cambia en consecuencia si cambio TOP n
. Por supuesto, dado que esta es una unión anidada, el número real de ejecuciones es 16k (el número de filas de la tabla A) y esto ralentiza la consulta.
El escenario real es un poco más complejo pero captura la idea / comportamiento básico. Ambas tablas se buscan utilizando búsquedas de índice. Esta es la edición Enterprise de SQL Server 2008 R2.
ORDER BY
cláusula. AgregandoTOP
cambios en el plan donde ocurre este tipo, pero estoy más preocupado por cómo afecta el número de ejecuciones de búsquedas de índice en la tabla B ... (por supuesto, los dos pueden estar relacionados, no lo sé)FAST num_rows
sugerencia de consulta.Respuestas:
La forma en que se expresa lo anterior me hace pensar que puede tener una imagen mental incorrecta de cómo se ejecuta una consulta. Un operador en un plan de consulta no es un paso (donde el conjunto de resultados completo de un paso anterior es evaluado por el siguiente.
SQL Server utiliza un modelo de ejecución canalizado , donde cada operador expone métodos como Init () , GetRow () y Close () . Como sugiere el nombre GetRow () , un operador produce una fila a la vez a pedido (según lo requiera su operador principal). Esto está documentado en la referencia de Operadores físicos y lógicos de los Libros en línea , con más detalles en la publicación de mi blog Por qué los planes de consulta se ejecutan al revés . Este modelo de fila a la vez es esencial para formar una intuición sólida para la ejecución de consultas.
Algunas operaciones lógicas como
TOP
, semiuniones y laFAST n
sugerencia de consulta afectan la forma en que el optimizador de consultas cuesta alternativas de plan de ejecución. La idea básica es que una posible forma de plan podría devolver las primeras n filas más rápidamente que un plan diferente que se optimizó para devolver todas las filas.Por ejemplo, la unión de bucles anidados indexados es a menudo la forma más rápida de devolver una pequeña cantidad de filas, aunque la combinación hash o fusionada con escaneos puede ser más eficiente en conjuntos más grandes. La forma en que el optimizador de consultas razona sobre estas opciones es estableciendo un Objetivo de fila en un punto particular del árbol lógico de operaciones.
Un objetivo de fila modifica la forma en que se calculan las alternativas del plan de consulta. La esencia de esto es que el optimizador comienza costando a cada operador como si se requiriera el conjunto de resultados completo, establece un objetivo de fila en el punto apropiado y luego retrocede en el árbol del plan estimando el número de filas que espera examinar. para cumplir el objetivo de la fila.
Por ejemplo, un lógico
TOP(10)
establece un objetivo de fila de 10 en un punto particular del árbol de consulta lógica. Los costos de los operadores que conducen al objetivo de la fila se modifican para estimar cuántas filas necesitan producir para alcanzar el objetivo de la fila. Este cálculo puede volverse complejo, por lo que es más fácil entender todo esto con un ejemplo completamente trabajado y planes de ejecución anotados. Los objetivos de fila pueden afectar más que la elección del tipo de combinación o si las búsquedas y búsquedas son preferibles a los escaneos. Más detalles sobre eso aquí .Como siempre, un plan de ejecución seleccionado en función de un objetivo de fila está sujeto a las capacidades de razonamiento del optimizador y a la calidad de la información que se le proporciona. No todos los planes con un objetivo de fila producirán el número requerido de filas más rápido en la práctica, pero de acuerdo con el modelo de costos lo hará.
Cuando un plan de objetivos de fila no sea más rápido, generalmente hay formas de modificar la consulta o proporcionar mejor información al optimizador de modo que el plan seleccionado de forma natural sea el mejor. La opción adecuada en su caso depende de los detalles, por supuesto. La función de objetivo de fila es generalmente muy efectiva (aunque hay un error a tener en cuenta cuando se usa en planes de ejecución paralelos).
Es posible que su consulta y plan en particular no sean adecuados para un análisis detallado aquí (de todos modos, proporcione un plan de ejecución real si lo desea), pero es de esperar que las ideas esbozadas aquí le permitan avanzar.
fuente
Cuando usa TOP, Optimizer ve la oportunidad de hacer menos trabajo. Si solicita 10 filas, entonces hay una buena posibilidad de que no necesite consumir todo el conjunto. Por lo tanto, el operador TOP puede ser empujado mucho más hacia la derecha. Seguirá solicitando filas al siguiente operador (a su derecha), hasta que haya recibido suficiente.
Señala que sin TOP, la consulta clasifica los datos al final. Si el motor pudiera saber cuántas filas iba a satisfacer la unión por adelantado, bien podría optar por utilizar un plan similar, colocando el TOP a la izquierda. Pero con el esfuerzo de hacer un Hash Match relativamente alto, y presumiblemente no hay opción para unir Merge Join, el Optimizador podría preferir filtrar el TOP más hacia la derecha.
Cuando se consulta la tabla B, se obtiene una sola fila a la vez. Es por eso que la estimación es 1. También supone que solo encontrará esa fila el 50% del tiempo. Entonces adivina que necesitará 2n + 1 busca encontrarlo.
fuente
TOP
cláusula? Gracias por su (s) respuesta (s) / paciencia.