一、 查詢要求
Q1語句查詢lineItem的一個定價總結報告。在單個表lineitem上查詢某個時間段內,對已經付款的、已經運送的等各類商品進行統計,包括業務量的計費、發貨、折扣、稅、平均價格等信息。
Q1語句的特點是:帶有分組、排序、聚集操作並存的單表查詢操作。這個查詢會導致表上的數據有95%到97%行被讀取到。
二、 Oracle執行
Oracle編寫的查詢SQL語句如下:
select /*+ parallel(n) */
l_returnflag,
l_linestatus,
sum(l_quantity) as sum_qty,
sum(l_extendedprice) as sum_base_price,
sum(l_extendedprice * (1 - l_discount)) as sum_disc_price,
sum(l_extendedprice * (1 - l_discount) * (1 + l_tax)) as sum_charge,
avg(l_quantity) as avg_qty,
avg(l_extendedprice) as avg_price,
avg(l_discount) as avg_disc,
count(*) as count_order
from
lineitem
where
l_shipdate <= date '1995-12-01' - interval '90' day(3)
group by
l_returnflag,
l_linestatus
order by
l_returnflag,
l_linestatus;
其中/*+ parallel(n) */ 是Oracle的並行查詢語法,n就是並行數。
腳本執行時間,單位:秒
三、 SPL優化
這是一個常規的分組查詢,結果集也不大,沒有特殊的優化技術,使用多路遊標充分利用並行即可。
編寫Q1查詢的SPL腳本如下:
其中A1格為設置的並行數量,後續其它例子均這樣約定。
這段代碼較為常規,A6定義多路遊標利用並行,因結果集不大,在A7使用groups做小分組。
腳本執行時間,單位:秒
可以看出,SPL的並行效果很好,接近線性提速。
單線程時SPL的性能也更好,這主要是因為組表採用了壓縮列式存儲。
本查詢涉及數據量較大,需要從外存讀入數據,硬盤訪問時間是不可忽略的因素。當計算未涉及全部數據列時,使用列式存儲能減少讀取量。而且,列存方式更容易壓縮,從而進一步減少硬盤訪問時間。
事實上,集算器SPL目前採用Java開發,如果單純對比CPU的計算性能,應當會弱於C++開發的Oracle。但是,因為壓縮列式存儲減少了硬盤訪問時間,這導致了慢速的Java也能跑過快速的C++。
不過,列存並非總是有效,如果採用機械硬盤,列式存儲會導致更多的尋道時間,雖然讀取量變少,但由於尋道導致的時間消耗很可能更多。而這次測試採用了SSD硬盤,沒有尋道時間的問題。
還需要值得注意的是,我們把過濾條件寫進了A6,也就是遊標建立的語句中。這樣,SPL在讀取數據時,如果發現條件不成立,將直接放棄讀取相關列,進一步減少硬盤訪問和記錄生成的時間。
四、 進一步優化
這個SQL是單表分組統計,沒有關聯,有過濾。lineitem這張表數據量很大,讀數耗時很長,如果能在過濾環節大幅度減少讀數的消耗,可以進一步提升性能。在業務許可時,如果設計組表時改用過濾字段l_shipdate作為維字段,則可以快速選出目標數據,提升查詢速度。
重新生成組表(此組表僅用於Q1查詢)的SPL腳本如下:
用此組表測試,查詢時間對比如下:
腳本執行時間,單位:秒
創建組表時不一定總按主鍵排序,如果事先知道查詢條件或者這個查詢條件很常用,則可以用查詢字段排序來提高性能。在使用中可以採取主鍵排序的組表和查詢字段排序的組表共存的策略,編寫某個查詢任務時可根據需要靈活選用某個組表。
閱讀更多 raqsoft 的文章