openGauss 支援SQL-PATCH

奔跑的数据库發表於2024-04-09

支援SQL PATCH

可獲得性

本特性自openGauss 3.0.0版本開始引入。

特性簡介

SQL PATCH能夠在避免直接修改使用者業務語句的前提下對查詢執行的方式做一定調整。在發現查詢語句的執行計劃、執行方式未達預期的場景下,可以透過建立查詢補丁的方式,使用Hint對查詢計劃進行調優或對特定的語句進行報錯短路處理。

客戶價值

在業務產生查詢計劃不優導致的效能問題或系統內部錯誤導致服務不可用問題時,可以在資料庫內透過運維函式呼叫對特定的場景進行調優或提前報錯,以規避更嚴重的問題,能夠大幅降低上述問題的運維成本。

特性描述

SQL PATCH主要設計給DBA、運維人員及其他需要對SQL進行調優的角色使用,使用者透過其他運維檢視或定位手段識別到業務語句存在計劃不優導致的效能問題時,可以透過建立SQL PATCH對業務語句進行基於Hint的調優。目前支援行數、掃描方式、連線方式、連線順序、PBE custom/generic計劃選擇、語句級引數設定、引數化路徑的Hint。此外,對於部分由特定語句觸發系統內部問題導致系統可服務性受損的語句,在不對業務語句變更的情況下,也可以透過建立用於單點規避的SQL PATCH,對問題場景提前報錯處理,避免更大的損失。

SQL PATCH的實現當前基於Unique SQL ID,所以需要開啟相關的運維引數才可以生效(詳見特性約束),Unique SQL ID在WDR報告和慢SQL檢視中都可以獲取到,在建立SQL PATCH時需要指定Unique SQL ID。下面給出簡單的使用樣例。

場景一:使用SQL PATCH對特定語句進行Hint調優。

openGauss=# set track_stmt_stat_level = 'L1,L1'; --開啟FullSQL統計資訊
SET
openGauss=# select * from hint_t1 t1 where t1.a = 1; --執行SQL語句
 a | b | c
---+---+---
 1 | 1 | 1
(1 row)
openGauss=# select unique_query_id, query, query_plan from dbe_perf.statement_history where query like '%hint_t1%'; --獲取查詢計劃和Unique SQL ID
-[ RECORD 1 ]---+----------------------------------------------------------------------------------------------
unique_query_id | 2578396627
query           | select * from hint_t1 t1 where t1.a = ?;
query_plan      | Datanode Name: sgnode
                | Bitmap Heap Scan on hint_t1 t1  (cost=4.33..15.70 rows=10 p-time=0 p-rows=0 width=12)
                |   Recheck Cond: (a = '***')
                |   ->  Bitmap Index Scan on hint_t1_a_idx  (cost=0.00..4.33 rows=10 p-time=0 p-rows=0 width=0)
                |         Index Cond: (a = '***')
                |
                |
openGauss=# select * from dbe_sql_util.create_hint_sql_patch('patch1', 2578396627, 'indexscan(t1)'); -- 對指定的Unique SQL ID指定Hint Patch
-[ RECORD 1 ]---------+--
create_hint_sql_patch | t
openGauss=# explain select * from hint_t1 t1 where t1.a = 1; -- 透過explain可以確認Hint是否生效
NOTICE:  Plan influenced by SQL hint patch
                                    QUERY PLAN
-----------------------------------------------------------------------------------
 [Bypass]
 Index Scan using hint_t1_a_idx on hint_t1 t1  (cost=0.00..32.43 rows=10 width=12)
   Index Cond: (a = 1)
(3 rows)
openGauss=# select * from hint_t1 t1 where t1.a = 1; -- 再次執行語句
 a | b | c
---+---+---
 1 | 1 | 1
(1 row)
openGauss=# select unique_query_id, query, query_plan from dbe_perf.statement_history where query like '%hint_t1%'; -- 可以看到新的執行記錄計劃已改變
-[ RECORD 1 ]---+--------------------------------------------------------------------------------------------------
unique_query_id | 2578396627
query           | select * from hint_t1 t1 where t1.a = ?;
query_plan      | Datanode Name: sgnode
                | Bitmap Heap Scan on hint_t1 t1  (cost=4.33..15.70 rows=10 p-time=0 p-rows=0 width=12)
                |   Recheck Cond: (a = '***')
                |   ->  Bitmap Index Scan on hint_t1_a_idx  (cost=0.00..4.33 rows=10 p-time=0 p-rows=0 width=0)
                |         Index Cond: (a = '***')
                |
                |
-[ RECORD 2 ]---+--------------------------------------------------------------------------------------------------
unique_query_id | 2578396627
query           | select * from hint_t1 t1 where t1.a = ?;
query_plan      | Datanode Name: sgnode
                | Index Scan using hint_t1_a_idx on hint_t1 t1  (cost=0.00..8.27 rows=1 p-time=0 p-rows=0 width=12)
                |   Index Cond: (a = '***')
                |
                |

場景二:使用SQL PATCH對特定語句進行提前報錯規避。

openGauss=# select * from dbe_sql_util.drop_sql_patch('patch1'); -- 刪去patch1
 drop_sql_patch
----------------
 t
(1 row)
openGauss=# select * from dbe_sql_util.create_abort_sql_patch('patch2', 2578396627); 對該語句的Unique SQL ID建立Abort Patch
 create_abort_sql_patch
------------------------
 t
(1 row)

openGauss=# select * from hint_t1 t1 where t1.a = 1; -- 再次執行語句會提前報錯
ERROR:  Statement 2578396627 canceled by abort patch patch2

特性增強

無。

特性約束

  1. 僅支援針對Unique SQL ID打PATCH,如果存在Unique SQL ID衝突,用於Hint調優的SQL PATCH可能影響效能,但不影響語義正確性。
  2. 僅支援不改變SQL語義的Hint作為PATCH,不支援SQL改寫。
  3. 不支援邏輯備份、恢復。
  4. 不支援建立時校驗PATCH合法性,如果PATCH的Hint存在語法或語義錯誤,不影響查詢正確執行。
  5. 僅初始使用者、運維管理員、監控管理員、系統管理員使用者有許可權執行。
  6. 庫之間不共享,建立SQL PATCH時需要連線目標庫。
  7. 配置集中式備機可讀時,需要指定主機執行SQL PATCH建立/修改/刪除函式呼叫,備機執行報錯。
  8. SQL PATCH同步給備機存在一定延遲,待備機回放相關日誌後PATCH生效。
  9. 不支援對儲存過程中的SQL語句生效,當前機制不會對儲存過程內語句生成Unique SQL ID。
  10. 用於規避的Abort Patch不建議在資料庫中長期使用,只應該作為臨時規避方法。遇到核心問題所導致的特定語句觸發資料庫服務不可用問題,需要儘快修改業務或升級核心版本解決問題。並且升級後由於Unique SQL ID生成方法可能變化,可能導致規避方法失效。
  11. 當前,除DML語句之外,其他SQL語句(如CREATE TABLE等)的Unique SQL ID是對語句文字直接雜湊生成的,所以對於此類語句,SQL PATCH對大小寫、空格、換行等敏感,即不同的文字的語句,即使語義相對,仍然需要對應不同的SQL PATCH。對於DML,則同一個SQL PATCH可以對不同入參的語句生效,並且忽略大小寫和空格。

依賴關係

本特性依賴於資源實時監控功能,需要開啟enable_resource_track引數並且設定instr_unique_sql_count大於0。對於不同的語句,如果生成的Unique SQL ID衝突,會導致SQL PATCH錯誤的命中預期外的其他語句。其中用於調優的Hint PATCH副作用相對較小,Abort Patch需要謹慎使用。