Ejemplo de consulta en paralelo

La consulta siguiente cuenta el número de pedidos realizados en un determinado trimestre, a partir del 1 de abril de 2000, y en los cuales el cliente recibió al menos un elemento de la línea del pedido después de la fecha de confirmación. Esta consulta muestra el número de dichos pedidos agrupados por orden de prioridad y de manera ascendente.

Este ejemplo utiliza una tabla y nombres de columnas teóricos.

SELECT o_orderpriority, COUNT(*) AS Order_Count
FROM orders
WHERE o_orderdate >= '2000/04/01'
   AND o_orderdate < DATEADD (mm, 3, '2000/04/01')
   AND EXISTS
         (
          SELECT *
            FROM    lineitem
            WHERE l_orderkey = o_orderkey
               AND l_commitdate < l_receiptdate
         )
   GROUP BY o_orderpriority
   ORDER BY o_orderpriority

Se supone que los índices siguientes están definidos en las tablas lineitem y orders:

CREATE INDEX l_order_dates_idx 
   ON lineitem
      (l_orderkey, l_receiptdate, l_commitdate, l_shipdate)

CREATE UNIQUE INDEX o_datkeyopr_idx
   ON ORDERS
      (o_orderdate, o_orderkey, o_custkey, o_orderpriority)

Éste es un posible plan en paralelo generado para la consulta mostrada anteriormente:

|--Stream Aggregate(GROUP BY:([ORDERS].[o_orderpriority])
                  DEFINE:([Expr1005]=COUNT(*)))
    |--Parallelism(Gather Streams, ORDER BY:
                  ([ORDERS].[o_orderpriority] ASC))
         |--Stream Aggregate(GROUP BY:
                  ([ORDERS].[o_orderpriority])
                  DEFINE:([Expr1005]=Count(*)))
              |--Sort(ORDER BY:([ORDERS].[o_orderpriority] ASC))
                   |--Merge Join(Left Semi Join, MERGE:
                  ([ORDERS].[o_orderkey])=
                        ([LINEITEM].[l_orderkey]),
                  RESIDUAL:([ORDERS].[o_orderkey]=
                        [LINEITEM].[l_orderkey]))
                        |--Sort(ORDER BY:([ORDERS].[o_orderkey] ASC))
                        |    |--Parallelism(Repartition Streams,
                           PARTITION COLUMNS:
                           ([ORDERS].[o_orderkey]))
                        |         |--Index Seek(OBJECT:
                     ([tpcd1G].[dbo].[ORDERS].[O_DATKEYOPR_IDX]),
                     SEEK:([ORDERS].[o_orderdate] >=
                           Apr  1 2000 12:00AM AND
                           [ORDERS].[o_orderdate] <
                           Jul  1 2000 12:00AM) ORDERED)
                        |--Parallelism(Repartition Streams,
                     PARTITION COLUMNS:
                     ([LINEITEM].[l_orderkey]),
                     ORDER BY:([LINEITEM].[l_orderkey] ASC))
                             |--Filter(WHERE:
                           ([LINEITEM].[l_commitdate]<
                           [LINEITEM].[l_receiptdate]))
                                  |--Index Scan(OBJECT:
         ([tpcd1G].[dbo].[LINEITEM].[L_ORDER_DATES_IDX]), ORDERED)

Plan de consulta con DOP 4, implica una combinación de dos tablas

En la ilustración se muestra un plan del optimizador de consultas que se ejecuta con un grado de paralelismo igual a 4 y que implica una combinación de dos tablas.

El plan en paralelo contiene tres operadores Parallelism. El operador Index Seek del índice o_datkey_ptr y el operador Index Scan del índice l_order_dates_idx se ejecutan en paralelo. Esto produce varias secuencias exclusivas. Esto puede determinarse a partir de los operadores Parallelism más cercanos que están delante de los operadores Index Scan e Index Seek, respectivamente. Ambos reparten el tipo de intercambio. Es decir, sólo reconstruyen los datos de las secuencias que producen el mismo número de secuencias en la salida que en la entrada. Este número de secuencias equivale al grado de paralelismo.

El operador Parallelism anterior al operador Index Scanl_order_dates_idx reparte sus secuencias de entrada con el valor de L_ORDERKEY como clave. De este modo, los mismos valores de L_ORDERKEY finalizan en la misma secuencia de salida. Al mismo tiempo, las secuencias de salida conservan el orden de la columna L_ORDERKEY para cumplir los requisitos de entrada del operador Merge Join.

El operador Parallelism anterior al operador Index Seek reparte sus secuencias de entrada con el valor de O_ORDERKEY. Como su entrada no está ordenada en los valores de la columna O_ORDERKEY y ésta es la columna de combinación del operador Merge Join, el operador Sort que está entre los operadores Parallelism y Merge Join asegura que la entrada esté ordenada para el operador Merge Join en las columnas de combinación. El operador Sort, al igual que el operador Merge Join, se ejecuta en paralelo.

El primer operador Parallelism recopila los resultados de varias secuencias en una sola secuencia. Las agregaciones parciales que realiza el operador Stream Aggregate que está a continuación del operador Parallelism, se acumulan en un solo valor SUM para cada valor diferente de O_ORDERPRIORITY en el operador Stream Aggregate anterior al operador Parallelism. Como este plan tiene dos segmentos de intercambio, y un grado de paralelismo igual a 4, utiliza ocho subprocesos.

Vea también

Conceptos