本文首發於 GreatSQL社區 微信公衆號。
GreatSQL馬上正式開源了,這次又新增了兩個重磅特性:InnoDB事務鎖優化 以及 InnoDB引擎的並行查詢優化,這兩個特性是由華爲鯤鵬計算團隊貢獻的Patch合併而來。
InnoDB並行查詢優化怎麼實現的?
根據B+樹的特點,可以將B+樹劃分爲若干子樹,此時多個線程可以並行掃描同一張InnoDB表的不同部分。對執行計劃進行多線程改造,每個子線程執行計劃與MySQL原始執行計劃一致,但每個子線程只需掃描表的部分數據,子線程掃描完成後再進行結果彙總。通過多線程改造,可以充分利用多核資源,提升查詢性能。
優化後,在TPC-H測試中表現優異,最高可提升30倍,平均提升15倍。
該特性適用於週期性數據彙總報表之類的SAP、財務統計等業務,例如月初、月底跑批業務等。
使用限制:
-
暫不支持子查詢,可想辦法改造成JOIN。 -
暫時只支持ARM架構平臺,X86架構平臺優化也會盡快完成。
關於該Patch詳情見:https://support.huaweicloud.com/fg-kunpengdbs/kunpengdbs_20_0005.html
本文針對 InnoDB引擎的並行查詢優化 特性進行對比測試。
1、測試環境
服務器:神州鯤泰R222,華爲Hi1616 * 2(主頻 2400 MHz 共64個邏輯CPU),256G內存。
操作系統:Docker 20.10.2,Docker容器下的CentOS Linux release 7.9.2009,Linux 4.15.0-29-generic。
本次測試採用TPC-H,dbgen構造測試數據參數 dbgen -vf -s 50
,導入後數據庫物理大小約70G。GreatSQL關鍵配置:
#運行Q10測試時,需要較大臨時表
temptable_max_ram = 6G
#使得本測試基於純內存場景
innodb_buffer_pool_size=96G
#InnoDB並行查詢優化
#global級別,設置並行查詢的開關,bool值,on/off。默認off,關閉並行查詢特性。可在線動態修改。
force_parallel_execute = ON
#global級別,設置系統中總的並行查詢線程數。有效值的範圍是(0, ULONG_MAX),默認值是64。
parallel_max_threads = 64
#global級別,並行執行時leader線程和worker線程使用的總內存大小上限。有效值的範圍是(0, ULONG_MAX),默認值是1G
parallel_memory_limit = 32G
2、測試數據
測試過程中,注意要確保每次查詢都是基於純內存的場景,也就是確保innodb_buffer_pool_size大於數據庫物理大小,並確認查詢過程中沒有額外的物理I/O發生。
個別SQL例如Q10在運行過程中會產生臨時表(Using temporary),這時候需要加大 temptable_max_ram 選項值。該選項默認值1G,在上述測試數據量前提下,大概需要加大到4G才能hold住。如果該選項值不夠的話,可能運行過程中會提示諸如 The table '/tmp/#sql57_a1_0' is full
這樣的錯誤提示,然後退出查詢,這是MySQL的BUG#99100。
InnoDB並行查詢特性通過HINT語法可以很方便地使用,首先確認啓用了該特性(可在線動態打開):
$ mysqladmin var|grep force_parallel_execute
| force_parallel_execute | ON
那麼默認所有的SQL只要符合條件,即可自動採用並行查詢,通過查看執行計劃確認:
mysql> EXPLAIN SELECT ... FROM ... WHERE ...
...
Parallel execute (4 workers)
...
可以看到執行計劃輸出中包含 Parallel execute (4 workers)
關鍵字,這就表示最高可並行4個線程查詢。
也可以查看樹狀執行計劃:
mysql> EXPLAIN FORMAT=TREE SELECT ... FROM ... WHERE ...
...
| -> Limit: 1 row(s)
-> Sort: lineitem.l_returnflag, lineitem.l_linestatus, limit input to 1 row(s) per chunk
-> Table scan on <temporary>
-> Aggregate using temporary table
-> Parallel scan on <temporary>
-> Sort: lineitem.l_returnflag, lineitem.l_linestatus
-> Table scan on <temporary>
-> Aggregate using temporary table
-> Filter: (lineitem.l_shipdate <= <cache>((DATE'1998-12-01' - interval '88' day))) (cost=6342898.28 rows=19669815)
-> PQblock scan on lineitem (cost=6342898.28 rows=59015354)
...
可以看到執行計劃中包含 PQblock scan on ...
關鍵字,並且注意到同一行裏提示 cost=6342898.28
,這是啓用並行查詢的條件之一,也就是 cost 超過了 parallel_cost_threshold = 1000
設置的閾值開關。
一條SQL若不想啓用並行查詢,加上相應的HINT即可:
mysql> SELECT /*+ NO_PQ */ ... FROM ... WHERE ...
也可以動態調整並行線程數爲最高64線程:
mysql> SELECT /*+ PQ(64) */ ... FROM ... WHERE ...
好了,直接查看結果對比數據:
TPCH | 並行掃描(默認參數) 耗時(秒) |
並行掃描(參數優化後) 耗時(秒) |
未優化前 耗時(秒) |
並行掃描 vs 未優化前的提升 | 提高查詢並行讀優化後提升 |
---|---|---|---|---|---|
Q1 | 616.407015 | 43.688772 | 1396.791060 | 31.971 | 14.109 |
Q3 | 139.579648 | 24.343778 | 330.946837 | 13.595 | 5.734 |
Q5 | 343.604734 | 30.501792 | 338.576433 | 11.100 | 11.265 |
Q6 | 248.830780 | 20.128220 | 233.490352 | 11.600 | 12.362 |
Q10 | 155.077042 | 41.948881 | 263.921069 | 6.291 | 3.697 |
Q12 | 325.281718 | 24.850585 | 582.405888 | 23.436 | 13.089 |
Q19 | 17.475904 | 5.296522 | 42.447522 | 8.014 | 3.300 |
從這個測試結果簡單概括幾條:
-
1、 平均提升約14倍,最高提升約32倍。 -
2、如果併發量更高,則優化效果更好。 -
3、Q5原始SQL性能提升不多,調整JOIN順序後性能提升顯著(從只提升28%躍升到11倍)。
GreatSQL將於近期正式開源,歡迎關注。
全文完。
Enjoy GreatSQL :)
文章推薦:
掃碼加入GreatSQL/MGR交流QQ羣
點擊文末“閱讀原文”直達老葉專欄
本文分享自微信公衆號 - 老葉茶館(iMySQL_WX)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。