sql >> Base de Datos >  >> RDS >> Database

Metas de Fila, Parte 3:Anti Joins

Esta publicación es parte de una serie de artículos sobre objetivos de fila. Puedes encontrar las otras partes aquí:

  • Parte 1:Establecer e identificar objetivos de fila
  • Parte 2:Semiuniones

Esta parte cubre cuándo y por qué el optimizador introduce un objetivo de fila para una unión anti.

Introducción

Una combinación anti también se conoce como una combinación anti semi. Devuelve cada fila de la entrada de unión A para la que no coincide se puede encontrar en la entrada B.

Para una unión anti:

  • El optimizador puede agregue un objetivo de fila interior a una aplicación (unión de bucles anidados correlacionados) solo anti-unión .
  • Un objetivo de fila no se agregó para bucles anidados no correlacionados anti-unión, hash anti-unión o fusión anti-unión.
  • Como siempre, cualquier objetivo de fila solo se agrega si es inferior a la estimación sin aplicar un objetivo de fila.
  • Lado interior redundante TOP cláusulas y DISTINCT/GROUP BY las operaciones se pueden simplificar.

Ampliando la primera viñeta anterior, la principal diferencia entre aplicar objetivos de semi-unión y aplicar objetivos de fila anti-unión es:

  • Una aplicación de unión semi siempre incluye un objetivo de fila (siempre que sea menor que la estimación sin la meta).
  • Una aplicación de combinación anti puede incluir un objetivo de fila , pero solo si una antiunión lógica se transforma en una aplicación durante la optimización basada en costos .

Me disculpo porque estas reglas no son más simples, pero yo no las hice. Con suerte, alguna discusión y ejemplos lo aclararán todo.

Sin objetivo de fila anti-unión por defecto

El optimizador asume que las personas escriben una semi unión (indirectamente, por ejemplo, usando EXISTS ) con la expectativa de que la fila que se busca se encontrará . Se ha establecido un objetivo de aplicar semiunión fila por el optimizador para ayudar a encontrar rápidamente la fila coincidente esperada.

Para anti unión (expresado, por ejemplo, usando NOT EXISTS ) la suposición del optimizador es que una fila coincidente no se encontrará . No se ha establecido un objetivo de fila anti-unión no establecido por el optimizador, porque espera tener que comprobar todas las filas para confirmar que no hay ninguna coincidencia.

Si resulta que hay una fila coincidente, la combinación anti aplicar puede tardar más en localizar esta fila que si se hubiera utilizado un objetivo de fila. Sin embargo, la combinación anti aún terminará su búsqueda tan pronto como se encuentre la coincidencia (inesperada).

Aplicar condiciones de objetivo de fila anti-unión

SQL Server no nos proporciona una forma de escribir una unión anti directamente, por lo que tenemos que usar soluciones alternativas como NOT EXISTS , NOT IN/ANY/SOME , o EXCEPT . Cada uno de estos formularios da como resultado una representación de subconsulta en el árbol analizado al comienzo de la compilación de la consulta. Esta subconsulta siempre se despliega en una aplicación y luego se transforma en una combinación lógica anti siempre que sea posible (los detalles son los mismos que para la unión semi discutida en la parte 2). Todo esto sucede incluso antes de que se considere un plan trivial.

Para que una combinación anti obtenga un objetivo de fila, debe ingresar optimización basada en costos como una contra unión lógica (lo que significa que la transformación de una aplicación anterior debe haber sido exitosa). Luego, el optimizador basado en costos debe optar por implementar la unión lógica anti como aplicar . Para que esto suceda, el optimizador primero debe elegir explorar la opción de aplicar; entonces debe seleccionar eso como la opción más barata (para esa parte del plan).

Cualquiera de las reglas de optimización basadas en costos establece un objetivo de fila anti-unión que puede transformar una unión en una aplicación. Un antijoin que entra optimización basada en costos como aplicación (porque falló la transformación a unión lógica anti) no tener un objetivo de fila aplicado.

El optimizador basado en costos solo explorará y seleccionará la opción de unirse para aplicar si hay una manera eficiente de ubicar las filas laterales internas coincidentes (por ejemplo, usando un índice). El optimizador no explorará la opción si el subárbol del lado interno de unión carece de algo útil para que el predicado de aplicación se "enganche". Esto podría ser un índice, un índice temporal (a través de un spool de índice ansioso) u otra clave lógica. Agregar el objetivo de la fila ayuda al optimizador a evaluar el costo de la opción de unirse para aplicar dado que se debe ubicar un máximo de una fila.

Tenga en cuenta que puede aparecer una combinación anti aplicar en un plan de ejecución sin un objetivo de fila. Esto ocurre cuando la transformación inicial de aplicar a unir falla, como es relativamente común. Cuando esto sucede, la combinación anti comienza a funcionar en el optimizador basado en costos como una aplicación, por lo que nunca se agrega un objetivo de fila por una de las reglas de combinación para aplicar.

Por supuesto, también se puede introducir un objetivo de fila en el lado interior de esta aplicación a través de un mecanismo diferente (no asociado con la aplicación), por ejemplo, mediante un operador superior independiente.

Para resumir:

  • Una unión anti solo puede obtener un objetivo de fila durante la optimización basada en costos (CBO).
  • Reglas que traducen una unión anti a un objetivo de agregar una fila.
  • La combinación anti debe ingresar CBO como una combinación, no como una aplicación.
  • Para ingresar CBO como una combinación, las fases anteriores deben poder reescribir la subconsulta como una combinación (a través de una etapa de aplicación).
  • CBO solo explora la combinación para aplicar la transformación en casos prometedores.

Ejemplo

Es un poco más complicado demostrar todo esto para aplicar anti-unión que para aplicar semi-unión. Las razones de esto se tratarán en la parte 4.

Mientras tanto, aquí hay un ejemplo de AdventureWorks que muestra cómo surge un objetivo de aplicar antiunión con fila, usando las mismas marcas de rastreo no documentadas que para semiunión. Se agrega el indicador de seguimiento 8608 para mostrar la estructura de memorándum inicial al comienzo de la optimización basada en costos.

SELECT P.ProductID 
FROM Production.Product AS P
WHERE 
    NOT EXISTS 
    (
        SELECT 1
        FROM Production.TransactionHistoryArchive AS THA 
        WHERE THA.ProductID = P.ProductID
 
        UNION ALL
 
        SELECT 1
        FROM Production.TransactionHistory AS TH 
        WHERE TH.ProductID = P.ProductID
    )
OPTION (QUERYTRACEON 3604, QUERYTRACEON 8607, QUERYTRACEON 8608, QUERYTRACEON 8612, QUERYTRACEON 8621);

La subconsulta existe primero se transforma en una aplicación: