1. 程式人生 > 資料庫 >一文為你詳解Unique SQL原理和應用

一文為你詳解Unique SQL原理和應用

摘要:以一定的演算法結合解析樹中的各結點,計算出來一個整數值,用來唯一標識這一類SQL,這個整數值被稱為Unique SQL ID,Unique SQL ID相同的SQL語句屬於同一個“Unique SQL”。

1、什麼是Unique SQL

使用者執行SQL語句時,每一個SQL語句文字都會進入解析器(Parser),生成“解析樹”(parse tree)。遍歷解析樹中各個結點,忽略其中的常數值,以一定的演算法結合樹中的各結點,計算出來一個整數值,用來唯一標識這一類SQL,這個整數值被稱為Unique SQL ID,Unique SQL ID相同的SQL語句屬於同一個“Unique SQL”。

例如,使用者先後輸入如下兩條SQL語句:

select * from t1 where id = 1;
select * from t1 where id = 2;

這兩條SQL語句除了過濾條件的常數值不同,其他地方都相同,由此生成的解析樹的拓撲結構完全相同,故Unique SQL ID也相同。因此兩條語句屬於如下同一個Unique SQL:

select * from t1 where id = ?;

GaussDB核心會對所有上面形式的SQL語句彙總統計資訊,通過檢視呈現給使用者。通過這種方式,可以排除一些無關的常量值的干擾,獲得某一類SQL語句的統計資料,為效能分析和問題定位提供數值依據。

注意,對於Unique SQL ID的計算,只會排除常數值,而不會排除其他的差異。例如,SQL語句“select * from t2 where id = 1;” 與上面的SQL不屬於同一個Unique SQL,不同使用者,從不同的CN節點執行的相同的SQL語句也不屬於同一個Unique SQL。

2、Unique SQL如何統計

收到SQL請求後,GaussDB核心首先算出其Unique SQL ID。如果該Unique SQL ID已存在,則直接更新相關的統計資訊。如果不存在,首先建立一個Unique SQL,然後再更新統計資訊,如下圖所示:

Unique SQL的統計資訊包括執行次數,響應時間,Cache/IO數量,行活動和時間分佈等資訊,可以通過如下兩個檢視查詢:

  • gs_instr_unique_sql
  • pgxc_instr_unique_sql

前者顯示當前CN(Coordinator Node)節點(執行當前SQL命令的節點)上的Unique SQL資訊,後者顯示系統中所有CN節點上的Unique SQL資訊。兩個檢視的格式相同,均由下表中的欄位組成:

3、如何使用Unique SQL

使用Unique SQL功能需要開啟以下變數開關:

  • enable_resource_check(預設為on)
  • track_counts(預設為on,影響行活動和Cache/IO相關欄位)

此外還需要將instr_unique_sql_count設為正整數。該變數預設為0,且不能在gsql會話中修改,需要通過SIGHUP的方式設定,例如:

gs_guc reload -Z coordinator -D /path/to/coordinator1/ -c "instr_unique_sql_count=20" > /dev/null

instr_unique_sql_count引數決定了系統收集的unique sql的數量。當收集的unique數量達到這個數後,新的sql不再被收集。如果將該數值改大,原有的unique sql資訊保留,同時開始收集新的unique sql。如果將該數值改小,則會清空當前CN節點所有已收集的unique sql資訊,然後開始收集新的unique sql。

設定好上述變數後,Unique sql統計檢視可以像普通檢視一樣查詢,例如:

postgres=# select node_name,query,n_calls from pgxc_instr_unique_sql;
  node_name   |                           query                            | n_calls
--------------+------------------------------------------------------------+---------
 coordinator2 | select node_name,query,n_calls from pgxc_instr_unique_sql; |       0
(1 row)

系統函式reset_instr_unique_sql可以清理unique sql資訊,該函式有3個引數,含義如下:

1. scope:如果為"GLOBAL",則清除所有CN節點上的資料;如果為"LOCAL",只清空當前CN上的資料。

2. type:如果為“ALL”,則清除所有資料;如果為"BY_USERID",只清除指定使用者的unique SQL;如果為"BY_CNID",只清除指定CN的unique SQL。

3. value:如果type=“ALL”,該引數無意義;如果type="BY_USERID",該引數為指定使用者的ID,如果type="BY_CNID",該引數為指定CN的ID。

例如:

postgres=# select reset_instr_unique_sql('global','all',0);
 reset_instr_unique_sql
------------------------
 t
(1 row)

此外,如果資料庫程序重啟,也會導致之前收集的unique SQL資訊被清空。

4、用Unique SQL輔助定位問題

unique sql檢視提供了豐富的資訊,使用者可以根據需要選取對自己有幫助的資訊使用。本節針對客戶在生產環境中遇到的實際情況,舉例說明幾種該檢視的使用方法,可供效能優化參考。

4.1 查詢異常的行活動導致的磁碟爭用

異常的行活動可能引起磁碟爭用,導致業務執行緩慢。通過檢視掃描的行數、返回的函式、更改的行數等指標的波動情況,可以發現異常的行活動,幫助定位原因。

postgres=# select sum(n_returned_rows) n_returned_rows, sum(n_tuples_fetched) n_tuples_fetched,
    sum(n_tuples_returned) n_tuples_returned, sum(n_tuples_inserted) n_tuples_inserted,
    sum(n_tuples_updated) n_tuples_updated, sum(n_tuples_deleted) n_tuples_deleted from pgxc_instr_unique_sql;
 n_returned_rows | n_tuples_fetched | n_tuples_returned | n_tuples_inserted | n_tuples_updated | n_tuples_deleted
-----------------+------------------+-------------------+-------------------+------------------+------------------
             234 |                0 |                 0 |                 0 |                0 |                0
(1 row)

4.2 查詢Top SQL對資源的佔用情況

可以基於執行時間、CPU時間、掃描行數、物理讀/邏輯讀等指標,對unique SQL檢視中的SQL語句進行排序,找出佔用資源最多的那些SQL語句,有針對性地其分析對效能的影響和原因,幫助查詢和定位問題。例如,

  • 按SQL執行時間順序或倒序排序:

SELECT user_name, unique_sql_id, query, total_elapse_time FROM pgxc_instr_unique_sql ORDER BY total_elapse_time ASC 或 DESC;

  • 按SQL執行佔用CPU時間進行順序或倒序排序:

SELECT user_name, unique_sql_id, query, cpu_time FROM pgxc_instr_unique_sql ORDER BY cpu_time ASC 或 DESC;

  • 按SQL順序掃描行數順序或倒序排序:

SELECT user_name, unique_sql_id, query, n_tuples_returned FROM pgxc_instr_unique_sql ORDER BY n_tuples_returned ASC 或 DESC;

  • 按SQL總掃描行進行順序或倒序排序:

SELECT user_name, unique_sql_id, query, n_tuples_fetched + n_tuples_returned FROM pgxc_instr_unique_sql ORDER BY n_tuples_fetched + n_tuples_returned ASC 或 DESC;

  • 按SQL執行執行器時間進行順序或倒序排序:

SELECT user_name, unique_sql_id, query, execution_time FROM pgxc_instr_unique_sql ORDER BY execution_time ASC 或 DESC;

  • 按SQL執行物理讀次數進行順序或倒序排序:

SELECT user_name, unique_sql_id, query, n_blocks_fetched FROM pgxc_instr_unique_sql ORDER BY n_blocks_fetched ASC 或 DESC;

  • 按SQL執行邏輯讀次數進行順序或倒序排序:

SELECT user_name, unique_sql_id, query, n_blocks_hit FROM pgxc_instr_unique_sql ORDER BY n_blocks_hit ASC 或 DESC;

4.3 查詢邏輯讀/物理讀數量

邏輯讀/物理讀過多可能導致SQL語句佔用較多的CPU時間。通過查詢unique SQL檢視可以得到sql語句邏輯/物理讀資料塊的數量,輔助判斷響應過慢的原因:

  • 查詢物理讀塊數量:

SELECT n_blocks_fetched FROM pgxc_instr_unique_sql;

  • 查詢邏輯讀塊數量:

SELECT n_blocks_hit FROM pgxc_instr_unique_sql;

4.4 診斷記憶體配額不足導致效能低下

如果資料庫緩衝區設定得太小,會導致每個SQL語句執行的結果不能被快取,當前SQL執行完畢如果有其他SQL執行就會把記憶體中上一個或上幾個SQL快取的執行結果擠出去,下一輪如果當前這個SQL再次執行時候又需要從磁碟進行物理IO讀取資料,而不能直接從快取中獲取資料,進而導致SQL執行效能較差。

緩衝區配額是否足夠大,可以通過命中率來判斷。緩衝區命中率=n_blocks_hit/n_blocks_fetched,可以通過查詢unique SQL來診斷是否存在記憶體配額不足的問題:

SELECT (n_blocks_hit/ n_blocks_fetched) AS hit_ratio from pgxc_instr_unique_sql;