從 TPCH 測試學習性能優化技巧之 Q3

一、 查詢要求

Q3語句查詢得到收入在前10位的尚未運送的訂單。在指定的日期之前還沒有運送的訂單中具有最大收入的訂單的運送優先級(訂單按照收入的降序排序)和潛在的收入(潛在的收入為l_extendedprice * (1-l_discount)的和)。

Q3語句的特點是:帶有分組、排序、聚集操作並存的三表查詢操作。查詢語句沒有從語法上限制返回多少條元組,TPC-H標準規定,查詢結果只返回前10行(通常依賴於應用程序實現)。

二、 Oracle執行

Oracle編寫的查詢SQL語句如下:

select * from (

select /+ parallel(n) /

l_orderkey,

sum(l_extendedprice * (1 - l_discount)) as revenue,

o_orderdate,

o_shippriority

from

customer,

orders,

lineitem

where

c_mktsegment = 'BUILDING'

and c_custkey = o_custkey

and l_orderkey = o_orderkey

and o_orderdate < date '1995-03-15'

and l_shipdate > date '1995-03-15'

group by

l_orderkey,

o_orderdate,

o_shippriority

order by

revenue desc,

o_orderdate

) where rownum<=10;

其中/*+ parallel(n) */ 是Oracle的並行查詢語法,n是並行數。

腳本執行時間,單位:秒

從 TPCH 測試學習性能優化技巧之 Q3

三、 SPL優化

這是典型的主子表關聯,SQL實現JOIN一般使用HASH算法,比較次數較多,在關聯兩表的數據均大於內存時還要做分段HASH,很難實現並行。

主子表的主鍵經過排序後,可以採用有序歸併的算法實現關聯,比較次數要少很多,而且無論數據量大小都很容易並行,SPL即支持這種寫法。

另外,本例SQL的GROUP BY子句中有三個字段:L_ORDERKEY、O_ORDERDATE、O_SHIPPRIORITY,原因是結果集中要輸出這三個字段。但事實上,後兩個字段可以被第一個字段決定,只要針對第一個字段進行分組,另兩個字段可根據第一個字段計算出來,不需要一起參與分組。這樣,在分組時的HASH計算和比對量都會少很多。

但是,SQL沒辦法寫出這樣的語法,只能把三個字段都寫進GROUP BY。SPL則可以寫出這樣的分組語法,減少計算量。

SPL腳本如下:

從 TPCH 測試學習性能優化技巧之 Q3

A7中對主子表做有序歸併時,因為主表order已被過濾,而主子表的主鍵同序,這時可以用news方法讀取子表時跳過主表中已經過濾掉的鍵值,從而減少子表的讀取量。

需要強調的是,lineitem必須按orders匹配的方法分段存儲,即開始準備數據時lineitem創建組表需要按L_ORDERKEY分段,這樣才能保證並行分段時不會錯位關聯。

A8的groups函數中使用了@o選項,這是因為我們知道連接後的結果集對L_ORDERKEY是有序的,因此可以使用有序分組的方法,這樣分組時只需要和上一條記錄進行比對,而不需要象常規分組時做hash計算和比對,計算性能要好得多。

如前所述,這裡的groups函數需要對L_ORDERKEY這一個字段分組,其它兩個字段可以直接取出,不需要再進行比對。

A7也使用了前面題目中說過的遊標建立時過濾的技巧。在A6中也有這種技巧,其中的A5.find,表示只需要把外鍵不匹配的記錄過濾掉,而不需要再轉換成指針。

腳本執行時間,單位:秒

從 TPCH 測試學習性能優化技巧之 Q3

可以看出,SPL的並行效果很好,接近線性提速。同時,這裡涉及大數據量,列存也能發揮作用。


分享到:


相關文章: