Parallel query example
Setting the max degree of parallelism option to 0 (default) enables SQL Server to use all
available processors up to a maximum of 64 processors in a parallel plan execution. Although
sets a runtime target of 64 logical processors when MAXDOP option is set to 0, a
different value can be manually set if needed. Setting MAXDOP to 0 for queries and indexes
allows SQL Server to use all available processors up to a maximum of 64 processors for the
given queries or indexes in a parallel plan execution. MAXDOP isn’t an enforced value for all
parallel queries, but rather a tentative target for all queries eligible for parallelism. This means
that if not enough worker threads are available at runtime, a query might execute with a lower
degree of parallelism than the MAXDOP server configuration option.
The following query counts the number of orders placed in a specific quarter, starting on April
1, 2000, and in which at least one line item of the order was received by the customer later
than the committed date. This query lists the count of such orders grouped by each order
priority and sorted in ascending priority order.
This example uses theoretical table and column names.
Assume the following indexes are defined on the
and
tables:
Tip
For more information, see
for guidelines on configuring
MAXDOP at the server, database, query, or hint level.
Here is one possible parallel plan generated for the query previously shown:
Output
The illustration below shows a query plan executed with a degree of parallelism equal to 4 and
involving a two-table join.
The parallel plan contains three parallelism operators. Both the Index Seek operator of the
index and the Index Scan operator of the
index are
performed in parallel. This produces several exclusive streams. This can be determined from the
nearest Parallelism operators above the Index Scan and Index Seek operators, respectively.
Both are repartitioning the type of exchange. That is, they are just reshuffling data among the
streams and producing the same number of streams on their output as they have on their
input. This number of streams is equal to the degree of parallelism.
The parallelism operator above the
Index Scan operator is repartitioning its
input streams using the value of
as a key. In this way, the same values of
end up in the same output stream. At the same time, output streams maintain the
order on the
column to meet the input requirement of the Merge Join operator.
The parallelism operator above the Index Seek operator is repartitioning its input streams using
the value of. Because its input isn’t sorted on the
column values and
this is the join column in the
operator, the Sort operator between the parallelism
and Merge Join operators make sure that the input is sorted for the
operator on
the join columns. The
operator, like the Merge Join operator, is performed in parallel.
The topmost parallelism operator gathers results from several streams into a single stream.
Partial aggregations performed by the Stream Aggregate operator below the parallelism
operator are then accumulated into a single
value for each different value of the
in the Stream Aggregate operator above the parallelism operator. Because
lineitem
orders
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
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)
|--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)
o_datkey_ptr
l_order_dates_idx
l_order_dates_idx
L_ORDERKEY
L_ORDERKEY
L_ORDERKEY
O_ORDERKEY
O_ORDERKEY
Merge Join
Merge Join
Sort
SUM
O_ORDERPRIORITY