摘要:雲堆棧的深度集成是釋放雲數據庫力量的關鍵,華為雲在實現這一目標方面處於領先地位,正如GaussDB(for MySQL)所證明的那樣。
本文分享自華為雲社區《近數據處理(NDP),為GaussDB(for MySQL)性能提升“加冕”》,作者: GaussDB 數據庫。
在上一篇文章《首席科學家為您揭秘:GaussDB(for MySQL)雲棧垂直集成的力量有多大》我們介紹了GaussDB(for MySQL)的體系架構,這篇文章我們將重點介紹GaussDB(for MySQL)如何將查詢處理卸載到存儲層,我們將這一特性稱之為近數據處理(Near Data Processing),簡稱NDP。
NDP出現的契機
在計算節點實例上執行查詢操作首先需要將數據頁面加載到InnoDB緩沖池(buffer pool)。相對傳統數據庫使用本地存儲,雲數據庫需要通過網絡獲取數據,因此從存儲節點讀取頁面數據的延遲要高得多。相比社區版MySQL,GaussDB(for MySQL)支持並行查詢,可通過多線程並行將數據讀取到緩沖池中,但當表數據量較大(包含數百萬甚至更多的數據行),分析查詢需要掃描大量數據時,將所需數據全部加載到緩沖池中,IO成本將變得非常高。因此,我們需要一種更優的方法來解決此問題。
我們的解決方案是基於GaussDB(for MySQL) 計算節點與存儲節點之間的緊密集成,將部分查詢處理操作下推至靠近數據的分布式存儲系統,數據庫術語中稱為算子下推。通過這種方式,我們可以利用多存儲節點的總帶寬。在雲環境中,存儲系統包含數百節點,我們希望充分利用存儲系統的可擴展性,同時避免網絡成為性能瓶頸點。NDP允許部分查詢處理以大規模並行的方式在存儲節點執行,並顯著的減少網絡IO。
NDP有諸多好處,包括:
- 利用多租戶大規模分布式雲存儲系統,在多節點並行處理數據
- 顯著減少網絡IO,只返回滿足WHERE條件的行(過濾)和查詢涉及的列(投影)或聚合操作的結果,而不是將完整的數據頁面從存儲節點返回至計算節點
- 避免大數量掃描導致經常訪問的數據頁面從緩存池中移除
那么存儲層是如何處理的呢?
算子下推通常適用於全表掃描、索引掃描、范圍查詢等場景。WHERE條件可下推至存儲層,當前支持的數據類型包括:
- 數值類型(numeric, integer, float, double)
- 時間類型(date, time, timestamp)
- 字符串類型(char, varchar)等
算子下推可以與計算節點的並行查詢完美結合,從概念上講,一個查詢首先在計算層(垂直擴展)拆分為多個worker線程並行處理,每個worker線程均可觸發算子下推。由於分布式存儲中數據分布的策略,每個worker線程的負載將分配至存儲系統的多個節點上(水平擴展),每個存儲節點都有線程池處理算子下推請求。
查詢是否啟用算子下推,是在查詢優化階段,優化器根據統計信息和執行計划自動決策的。此外用戶還可以使用 hint 來控制查詢操作是否開啟算子下推。
算子下推可以很好地處理冷數據,然而,GaussDB(for MyQL)是一個OLTP系統,通常包含並發更新操作。當前計算下推實現,MVCC處理僅在計算節點進行,存儲節點只處理可見的行,針對無法判斷可見性的行,原樣返回至計算節點,通過undo-log回放出對應的數據。
通過算子下推,我們將獲得怎樣的收益呢?
以TPC-H標准測試集(scale factor: 100)為例,CPU:16核,內存: 128GB,計算節點數據庫緩沖池大小設置為80GB,采用冷數據進行驗證。
下圖展示了TPC-H Q6, Q12, Q14, Q15 4 個Query的查詢結果,均有20-40倍的性能提升。以Q12為例,只開啟NDP,借助分布式存儲算力和網絡IO縮減,性能提升5倍,同時在計算節點開啟並行查詢,又獲得7倍性能提升,總體提升約35倍,這個提升效果是非常顯著的。
本文中提到的這些功能都可在實際生產環境中使用,而這只是開始,隨着我們將更多計算推送到存儲層,更多的查詢將從此優化中受益,我們可以期待更大的性能提升。
如何啟用NDP?
開啟NDP開關,對當前Session生效,優化器自動判斷是否進行計算下推。
mysql> show variables like 'ndp_mode'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | ndp_mode | ON | +---------------+-------+ 1 row in set (0.00 sec) mysql> explain select count(*) from lineitem; +----+-------------+----------+------------+-------+---------------+---------+---------+------+-----------+----------+-------------------------------------------------------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+----------+------------+-------+---------------+---------+---------+------+-----------+----------+-------------------------------------------------------------------+ | 1 | SIMPLE | lineitem | NULL | index | NULL | PRIMARY | 8 | NULL | 594000899 | 100.00 | Using pushed NDP columns; Using pushed NDP aggregate; Using index | +----+-------------+----------+------------+-------+---------------+---------+---------+------+-----------+----------+-------------------------------------------------------------------+ 1 row in set, 1 warning (0.00 sec)
通過hint方式,使NDP對當前Query生效。
mysql> show variables like 'ndp_mode'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | ndp_mode | OFF | +---------------+-------+ 1 row in set (0.00 sec) mysql> explain select count(*) from lineitem; +----+-------------+----------+------------+-------+---------------+---------+---------+------+-----------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+----------+------------+-------+---------------+---------+---------+------+-----------+----------+-------------+ | 1 | SIMPLE | lineitem | NULL | index | NULL | PRIMARY | 8 | NULL | 594000899 | 100.00 | Using index | +----+-------------+----------+------------+-------+---------------+---------+---------+------+-----------+----------+-------------+ 1 row in set, 1 warning (0.00 sec) mysql> explain select/*+ ndp_pushdown() */ count(*) from lineitem; +----+-------------+----------+------------+-------+---------------+---------+---------+------+-----------+----------+-------------------------------------------------------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+----------+------------+-------+---------------+---------+---------+------+-----------+----------+-------------------------------------------------------------------+ | 1 | SIMPLE | lineitem | NULL | index | NULL | PRIMARY | 8 | NULL | 594000899 | 100.00 | Using pushed NDP columns; Using pushed NDP aggregate; Using index | +----+-------------+----------+------------+-------+---------------+---------+---------+------+-----------+----------+-------------------------------------------------------------------+ 1 row in set, 1 warning (0.00 sec)
挑戰與今后方向
NDP有諸多好處,但它也有一些技術挑戰需要我們解決。如分布式存儲系統為多租戶共享,為了避免不同租戶對資源爭搶使用,我們需要實現單租戶級的資源管控。另外是優化器決策使用NDP的時機,需結合觸發網絡IO讀取的數據量以及已緩存在緩沖池中的數據量綜合考慮。
GaussDB(for MySQL)是一款雲原生數據庫,該體系結構支持極其強大和靈活的NDP框架。未來,我們計划利用此框架不僅僅是做查詢處理,還將進一步擴展存儲層中的數據庫功能,這些功能可以與查詢下推結合使用。我們相信,雲堆棧的深度集成是釋放雲數據庫力量的關鍵,華為雲在實現這一目標方面處於領先地位,正如GaussDB(for MySQL)所證明的那樣。
請大家保持關注,我們后續將會給大家帶來更多精彩技術分享。也歡迎大家前往華為雲官網,了解更多GaussDB(for MySQL)詳情:https://www.huaweicloud.com/product/gaussdb_mysql.html