Share via


平行查詢範例

下列查詢會計算從 2000 年 4 月 1 日起,某一季之內所下的訂單數量,而這一季的訂單中,至少有一項產品晚於交付日期才送達客戶。這個查詢會列出這類的訂單數量,並依訂單的優先順序分組,然後以遞增的優先順序排序訂單。

這個範例使用假設性的資料表和資料行名稱。

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

假設下列索引是在 lineitemorders 資料表上定義的:

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)

使用 DOP 4 的查詢計畫,牽涉到兩個資料表的聯結

上圖所示為使用平行處理原則程度 4 來執行的查詢最佳化工具計畫,包含兩個資料表的聯結。

平行計畫包含三個平行處理原則運算子。o_datkey_ptr 索引的 Index Seek 運算子以及 l_order_dates_idx 索引的 Index Scan 運算子會以平行方式執行。這會產生數個獨佔的資料流。可分別從 Index ScanIndex Seek 運算子上方最接近的 Parallelism 運算子來判斷。兩者都會重新分割交換類型。也就是說,它們只是將資料流間的資料重新改組,然後依據其輸入的資料流數量產生等量的輸出資料流。此資料流數量就等於平行處理原則的程度。

l_order_dates_idxIndex Scan 運算子上的 Parallelism 運算子會使用 L_ORDERKEY 值做為索引鍵,以重新分割其輸入資料流。利用這種方式,相同的 L_ORDERKEY 值也會在相同的輸出資料流中產生相同的結果。同時,輸出資料流會維持 L_ORDERKEY 資料行的順序,以符合 Merge Join 運算子的輸入需求。

Index Seek 運算子上方的 Parallelism 運算子會使用 O_ORDERKEY 值,重新分割其輸入資料流。因為其輸入未在 O_ORDERKEY 資料行值上進行排序,而且此為 Merge Join 運算子的聯結資料行,所以介於 ParallelismMerge Join 運算子之間的 Sort 運算子,可確保會在聯結資料行上針對 Merge Join 運算子為輸入進行排序。Sort 運算子 (如 Merge Join 運算子) 會以平行方式執行。

最頂端的 Parallelism 運算子會將數個資料流中的結果,集合成單一資料流。接著,在 Parallelism 運算子下方之 Stream Aggregate 運算子所執行的部份彙總,會累積為 Parallelism 運算子上方之 Stream Aggregate 運算子中,各個不同 O_ORDERPRIORITY 值的單一 SUM 值。由於此計畫具有兩個交換區段,且平行處理原則的程度為 4,因此會使用八個執行緒。

請參閱

概念