Normalmente creo guías de plan construyendo primero una consulta que usa el plan correcto y copiándola en una consulta similar que no lo hace. Sin embargo, eso a veces es complicado, especialmente si la consulta no es exactamente la misma. ¿Cuál es la forma correcta de crear guías de plan desde cero?
SQLKiwi ha mencionado la elaboración de planes en SSIS, ¿hay alguna forma o herramienta útil para ayudar a diseñar un buen plan para SQL Server?
La instancia específica en cuestión es este CTE: SQLFiddle
with cte(guid,other) as (
select newid(),1 union all
select newid(),2 union all
select newid(),3)
select a.guid, a.other, b.guid guidb, b.other otherb
from cte a
cross join cte b
order by a.other, b.other;
¿Hay ALGUNA forma de hacer que el resultado arroje exactamente 3 guid
sy no más? Espero poder responder mejor a las preguntas en el futuro al incluir guías de plan con consultas de tipo CTE a las que se hace referencia varias veces para superar algunas peculiaridades de SQL Server CTE.
fuente
Respuestas:
Hoy no. Las expresiones de tabla común (CTE) no recursivas se tratan como definiciones de vista en línea y se expanden en el árbol de consulta lógica en cada lugar al que se hace referencia (al igual que las definiciones de vista regulares) antes de la optimización. El árbol lógico para su consulta es:
Observe los dos anclajes de vista y las seis llamadas a la función intrínseca
newid
antes de que comience la optimización. Sin embargo, muchas personas consideran que el optimizador debería poder identificar que los subárboles expandidos eran originalmente un solo objeto referenciado y simplificar en consecuencia. También ha habido varias solicitudes de Connect para permitir la materialización explícita de una tabla CTE o derivada.Una implementación más general haría que el optimizador considerara materializar expresiones comunes arbitrarias para mejorar el rendimiento (
CASE
con una subconsulta es otro ejemplo donde pueden ocurrir problemas hoy en día). Microsoft Research publicó un documento (PDF) sobre eso en 2007, aunque sigue sin implementarse hasta la fecha. Por el momento, estamos limitados a la materialización explícita usando cosas como variables de tabla y tablas temporales.Esto fue solo una ilusión de mi parte, y fue mucho más allá de la idea de modificar las guías del plan. Es posible, en principio, escribir una herramienta para manipular directamente el XML del plan de presentación, pero sin una instrumentación optimizadora específica, usar la herramienta probablemente sería una experiencia frustrante para el usuario (y el desarrollador piensa en ello).
En el contexto particular de esta pregunta, dicha herramienta aún sería incapaz de materializar el contenido de CTE de una manera que podría ser utilizada por múltiples consumidores (para alimentar ambas entradas a la unión cruzada en este caso). El optimizador y el motor de ejecución son compatibles con los carretes de múltiples consumidores, pero solo para fines específicos, ninguno de los cuales podría aplicarse a este ejemplo en particular.
Aquí hay una cantidad razonable de flexibilidad. La forma amplia del plan XML se utiliza para guiar la búsqueda de un plan final (aunque muchos atributos se ignoran por completo, por ejemplo, el tipo de partición en los intercambios) y las reglas de búsqueda normales también se relajan considerablemente. Por ejemplo, se desactiva la poda temprana de alternativas basadas en consideraciones de costos, se permite la introducción explícita de combinaciones cruzadas y se ignoran las operaciones escalares.
Hay demasiados detalles para profundizar, pero no se puede forzar la colocación de Filtros y Calcular escalares, y los predicados del formulario
column = value
se generalizan para que un plan que contengaX = 1
oX = @X
se pueda aplicar a una consulta que contengaX = 502
oX = @Y
. Esta flexibilidad particular puede ayudar enormemente a encontrar un plan natural para forzar.En el ejemplo específico, constante Union All siempre se puede implementar como una exploración constante; el número de entradas a la Unión Todos no importa.
fuente
No hay forma (versiones de SQL Server hasta 2012) de reutilizar un solo spool para ambas ocurrencias del CTE. Los detalles se pueden encontrar en la respuesta de SQLKiwi. Más abajo hay dos formas de materializar el CTE dos veces, lo cual es inevitable por la naturaleza de la consulta. Ambas opciones resultan en un recuento de guid neto distinto de 6.
El enlace del comentario de Martin al sitio de Quassnoi en un blog sobre el plan para guiar a un CTE fue una inspiración parcial para esta pregunta. Describe una forma de materializar un CTE con el propósito de una subconsulta correlacionada, a la que se hace referencia solo una vez, aunque la correlación puede hacer que se evalúe varias veces. Eso no se aplica a la consulta en la pregunta.
Opción 1 - Guía del plan
Tomando pistas de la respuesta de SQLKiwi, he reducido la guía a un mínimo que todavía hará el trabajo, por ejemplo, los
ConstantScan
nodos solo enumeran 2 operadores escalares que pueden expandirse lo suficiente a cualquier número.Opción 2 - Escaneo remoto
Al aumentar el gasto de la consulta e introducir una exploración remota, el resultado se materializa.
fuente
Con toda seriedad, no puede cortar planes de ejecución xml desde cero. Crearlos usando SSIS es ciencia ficción. Sí, todo es XML, pero son de universos diferentes. Al mirar el blog de Paul sobre ese tema , está diciendo "mucho en la forma en que SSIS permite ...", ¿entonces posiblemente ha entendido mal? No creo que esté diciendo "use SSIS para crear planes", sino "no sería genial poder crear planes usando una interfaz de arrastrar y soltar como SSIS". Tal vez, para una consulta muy simple, podría manejar esto, pero es una exageración, posiblemente incluso una pérdida de tiempo. Trabajo ocupado, se podría decir.
Si estoy creando un plan para una sugerencia o guía de plan USE PLAN, tengo un par de enfoques. Por ejemplo, podría eliminar registros de las tablas (por ejemplo, en una copia de la base de datos) para influir en las estadísticas y alentar al optimizador a tomar una decisión diferente. También he usado variables de tabla en lugar de todas las tablas en la consulta, por lo que el optimizador cree que cada tabla contiene 1 registro. Luego, en el plan generado, reemplace todas las variables de la tabla con los nombres de la tabla original e intercambie como el plan. Otra opción sería utilizar la opción WITH STATS_STREAM de ACTUALIZAR ESTADÍSTICAS para falsificar estadísticas, que es el método utilizado para clonar copias de bases de datos solo estadísticas.
He pasado algún tiempo jugando con los planes de ejecución xml en el pasado y he descubierto que al final, SQL simplemente dice "No estoy usando eso" y ejecuta la consulta como quiere de todos modos.
Para su ejemplo específico, estoy seguro de que sabe que puede usar set rowcount 3 o TOP 3 en la consulta para obtener ese resultado, pero supongo que ese no es su punto. La respuesta correcta sería realmente: usar una tabla temporal. Votaría que:) No sería una respuesta correcta "pasar horas, incluso días, cortando su propio plan de ejecución XML personalizado en el que intenta engañar al optimizador para que haga un spool perezoso para el CTE que de todos modos podría no funcionar, parecería inteligente pero también sería imposible de mantener ".
No intento ser poco constructivo allí, solo mi opinión, espero que ayude.
fuente
Finalmente en SQL 2016 CTP 3.0 hay una forma, tipo de:)
Usando el indicador de seguimiento y los eventos extendidos como detalla Dmitry Pilugin aquí , puede extraer (de forma algo arbitraria) tres guías únicas de las etapas intermedias de la ejecución de la consulta.
Nota: este código NO está destinado a la producción o al uso serio con respecto al forzamiento del plan CTE, simplemente una mirada alegre a un nuevo indicador de rastreo y una forma diferente de hacer las cosas:
Probado en la versión (CTP3.2) - 13.0.900.73 (x64), solo por diversión.
fuente
Encontré que traceflag 8649 (plan paralelo de fuerza) indujo este comportamiento para la columna de guía izquierda en mis instancias de 2008, R2 y 2012. No necesitaba usar la bandera en SQL 2005 donde el CTE se comportó correctamente. Intenté usar el plan generado en SQL 2005 en las instancias superiores, pero no valió.
Ya sea usando la pista, usando una guía de plan que incluya la pista o usando el plan generado por la consulta con la pista activada en un PLAN DE USO, etc. todo funcionó.
fuente