一、 問題背景與適用場景

在《性能優化技巧:有序歸併》中我們驗證了有序歸併算法提高關聯性能的效果,那麼還有沒有進一步提升的空間呢?能不能再減少數據的讀取量從而再提速呢?

通常主子關聯後還會再施加更多運算,比如過濾。有序歸併算法將主子表先分別讀出再做關聯,當其中一個關聯表被過濾後剩下記錄少了很多時,另一個關聯表也會有大量記錄不能關聯上,但做歸併關聯之前並不知道,仍然會將這些不可能關聯上的數據讀出,浪費了時間。

如果我們能根據被過濾表的主鍵去另一個表查找可被關聯記錄再來做關聯,那樣就能省去很多讀取動作了。而由於組表是按鍵有序存放的,恰恰能使我們可以用鍵值高速定位記錄,從而實現這個想法。

下面我們就做個測試,與常規有序歸併對比一下,看看性能提升的效果,並在測試過程中進一步分析一下提速原理。

二、 測試環境

測試機有兩個Intel2670 CPU,主頻2.6G,共16核,內存128G,SSD固態硬盤。

採用TPCH標準生成的200G數據,主表是orders,子表是lineitem。兩表中記錄分別按O_ORDERKEY、L_ORDERKEY升序排列。因數據量比較大,單線程運行時間較長,所以使用4線程並行測試。

三、 主表有過濾

查詢時對主表的過濾條件是O_TOTALPRICE>price,price是個參數,用來測試主表過濾後不同數據規模下的效果。

1. 常規有序歸併

編寫SPL腳本如下:

2. 有序定位關聯

編寫SPL腳本如下:

A3中創建子表遊標時沒有使用cursor函數,而是使用的news函數,表示在主表遊標的基礎上,用有序定位歸併後生成主子表關聯後的遊標,所以也不需要再用joinx進行關聯了。

3. 測試結果及分析

主表orders總記錄3億,測試結果列表如下:

比較兩段SPL腳本,主表遊標的創建是一樣的,在常規有序歸併中子表遊標是獨立創建,會把子表記錄中的每條記錄所需的3個字段全部讀出,然後在joinx的時候再把兩個遊標的記錄進行有序歸併。而在有序定位關聯中,是根據已經過濾後的主表記錄的關聯字段值,去子表有序查找所對應的關聯字段值。組表數據是分塊存儲的,組表索引頭會記着每塊主鍵的最大最小值,如果發現關聯鍵值大於當前塊的最大值,就可以直接跳過這一塊,再重新定位到包含這個鍵值的數據塊去讀。而且在比對的時候,只需要先讀關聯字段值,如果值不同而關聯不上,則其它2個字段就不用讀,值關聯了才把其它2個字段讀出來。

測試結果驗證上述原理:在主表各種過濾規模下,使用有序定位關聯均能較大地提高性能。

四、 子表有過濾

查詢時對子表的過濾條件是L_QUANTITY >quantity,quantity是個參數,用來測試子表過濾後不同數據規模下的效果。

1. 常規有序歸併

編寫SPL腳本如下:

2. 有序定位關聯

編寫SPL腳本如下:

A3中使用new創建主表遊標,同時用sum對子表數據按關聯鍵分組求和後作爲主表的一個字段值。

3. 測試結果及分析

子表lineitem總記錄12億,測試結果列表如下:

這兩段SPL腳本和前面主表過濾的測試差不多,不同的只是使用過濾後的子表來關聯主表,需要使用new函數。提速原理也和前面相同,已經過濾後的子表,再與主表關聯時,只會讀出能關聯上的主表記錄,不必完全遍歷整個主表。從而減少數據讀取量。

從測試結果看,隨着過濾後剩下的子表記錄越來越少,減少數據讀取量的優勢也越來越小,性能提升幅度變小。

五、 結論

對於有過濾的主子表關聯查詢,使用有序定位關聯算法經常能獲得更好的性能。

相關文章