全部產品
Search
文件中心

PolarDB:polar_plsql_profiler

更新時間:Jan 06, 2026

當PL/SQL函數或預存程序變得複雜時,您可能會發現難以定位其中的效能瓶頸。POLAR_PLSQL_PROFILER外掛程式能夠監控並記錄PL/SQL代碼的執行細節,協助您精確分析每一行代碼的執行耗時和函數間的調用關係,從而有效地進行效能最佳化。

功能簡介

POLAR_PLSQL_PROFILER是一個效能分析工具,它通過掛載到PL/SQL的執行引擎上,在代碼運行時採集效能資料。這些資料包括每行代碼的執行次數、累計耗時,以及函數之間的調用層級和時間分布。分析器將採集到的資料存放區在當前會話的記憶體中,您可以通過調用其提供的函數,以結構化資料或可視化HTML報告的形式查看分析結果。

適用範圍

支援的PolarDB PostgreSQL版(相容Oracle)的版本: Oracle文法相容 2.0,且核心小版本需為2.0.14.19.40.0及以上。

說明

您可在控制台查看核心小版本號碼,也可以通過SHOW polardb_version;語句查看。如未滿足核心小版本要求,請升級核心小版本

優勢

  • 程式碼級分析:能夠精確到每一行原始碼的執行次數和耗時,快速定位熱點代碼。

  • 調用圖譜:清晰展示函數間的調用關係,協助理解整體耗時在不同函數模組間的分布。

  • 可視化報告:支援一鍵產生內容詳盡的HTML報告,便於分析和分享。

注意事項

  • 效能開銷:開啟效能分析會帶來額外的效能開銷,建議僅在開發或效能診斷情境中使用,避免在生產環境中長時間開啟。

  • 會話層級:分析器採集的資料僅在當前資料庫會話中有效。會話斷開後,所有分析資料將丟失。

  • 及時清理:分析結束後,請及時禁用分析器並清理資料,以釋放資源並消除效能影響。

操作指南

為了更好地展示工具的使用,以下將通過兩個樣本進行講解:一個用於快速入門,另一個用於示範如何分析包含子函數調用的複雜情境。

快速入門與基本分析

本樣本將引導您完成一次最基本的效能分析流程。

步驟一:安裝外掛程式

在使用前,請先建立外掛程式並啟用分析器。分析器將開始監控當前會話中所有PL/SQL代碼的執行。

-- 建立外掛程式(如果尚未建立)
CREATE EXTENSION polar_plsql_profiler;

步驟二:準備範例程式碼

執行您需要分析效能的PL/SQL函數或預存程序。以下是一個樣本函數:

-- 建立一個用於測試的函數
CREATE OR REPLACE FUNCTION simple_test_func(p_times IN NUMBER)
RETURNS VARCHAR2 AS
    v_result VARCHAR2(100);
BEGIN
    FOR i IN 1 .. p_times LOOP
        v_result := 'Iteration ' || i;
    END LOOP;
    RETURN v_result;
END;

步驟三:啟用分析器

啟動分析器,啟用成功將返回t

SELECT plsql_profiler_enable();

步驟四:執行目標代碼

執行函數以收集資料。

SELECT simple_test_func(100);

步驟五:分析效能資料

可以通過多種方式查看採集到的效能資料。

查看函數調用概覽

使用plsql_profiler_show_funclist()函數可以查看本次分析中所有被調用函數的總體效能統計,協助您快速識別耗時最長的函數。

SELECT * FROM plsql_profiler_show_funclist();

返回結果如下:

              func_call               | func_oid_list | call_count | us_total | us_declare | us_children | us_self |          time_stamp           
--------------------------------------+---------------+------------+----------+------------+-------------+---------+-------------------------------
 oid=21749  public.simple_test_func() | {21749}       |          1 |      303 |         13 |           0 |     303 | 2026-01-05 06:01:20.619468+00

查看指定函數的行級詳情

當定位到目標函數後,使用plsql_profiler_show_function()可以查看該函數內部每一行代碼的詳細效能資料。

-- 首先,從函數列表中擷取目標函數的OID數組(func_oid_list)
-- 然後,將該OID數組作為參數傳入以下函數
SELECT * FROM plsql_profiler_show_function(ARRAY['...']); -- 請將'...'替換為函數OID列表

樣本

SELECT * FROM plsql_profiler_show_function(ARRAY[21749]);

返回結果如下:

 line_number | exec_count | total_time | percent | avg_time | min_time | max_time |              source_code               | time_stamp 
-------------+------------+------------+---------+----------+----------+----------+----------------------------------------+------------
           0 |          1 |        303 |     100 |      303 |      303 |      303 |  ---- Function Totals ----             | 
           1 |          0 |          0 |       0 |        0 |        0 |        0 | v_result VARCHAR2(100);                | 
           2 |          1 |        287 |   94.72 |      287 |      287 |      287 | BEGIN                                  | 
           3 |          1 |        276 |   91.09 |      276 |      276 |      276 |     FOR i IN 1 .. p_times LOOP         | 
           4 |        100 |        145 |   47.85 |        1 |        0 |      145 |         v_result := 'Iteration ' || i; | 
           5 |          0 |          0 |       0 |        0 |        0 |        0 |     END LOOP;                          | 
           6 |          1 |          0 |       0 |        0 |        0 |        0 |     RETURN v_result;                   | 
           7 |          0 |          0 |       0 |        0 |        0 |        0 | END;                                   | 

步驟六:清理資源

分析工作完成後,執行以下操作來重設資料、禁用分析器並移除外掛程式,以避免對後續操作產生效能影響。

-- 1. (可選)重設已採集的分析資料
SELECT plsql_profiler_reset();

-- 2. 禁用分析器
SELECT plsql_profiler_disable();

-- 3. (可選)如果不再需要,可以刪除外掛程式
DROP EXTENSION polar_plsql_profiler;

深入分析與定位瓶頸(含子函數調用)

本樣本將類比一個更真實的情境:一個主函數調用一個耗時的子函數。我們將示範如何通過分析器找到真正的效能瓶頸。

步驟一:安裝外掛程式

在使用前,請先建立外掛程式並啟用分析器。分析器將開始監控當前會話中所有PL/SQL代碼的執行。

-- 建立外掛程式(如果尚未建立)
CREATE EXTENSION polar_plsql_profiler;

步驟二:準備範例程式碼

首先,建立一個包含子函數的複雜包。

-- 建立包含子函數的複雜包
CREATE OR REPLACE PACKAGE complex_pkg AS
    FUNCTION calculate_tax(p_salary NUMBER) RETURN NUMBER;
    PROCEDURE process_payroll(p_dept_id NUMBER);
END complex_pkg;

CREATE OR REPLACE PACKAGE BODY complex_pkg AS
    FUNCTION calculate_tax(p_salary NUMBER) RETURN NUMBER IS
        v_tax_amount NUMBER;
        -- 子函數
        FUNCTION get_tax_rate(p_income NUMBER) RETURN NUMBER IS
            v_rate NUMBER;
        BEGIN
            IF p_income <= 50000 THEN
                v_rate := 0.10;
            ELSIF p_income <= 100000 THEN
                v_rate := 0.20;
            ELSE
                v_rate := 0.30;
            END IF;
            RETURN v_rate;
        END get_tax_rate;
    BEGIN
        v_tax_amount := p_salary * get_tax_rate(p_salary);
        RETURN v_tax_amount;
    END calculate_tax;

    PROCEDURE process_payroll(p_dept_id NUMBER) IS
    BEGIN
        -- 執行一些操作
        NULL;
    END process_payroll;
END complex_pkg;

步驟三:啟用分析器

啟動分析器,啟用成功將返回t

SELECT plsql_profiler_enable();

步驟四:執行目標代碼

執行函數以收集資料。

SELECT complex_pkg.calculate_tax(75000);

步驟五:分析效能資料

可以通過多種方式查看採集到的效能資料。

查看函數調用概覽

使用plsql_profiler_show_funclist()函數可以查看本次分析中所有被調用函數的總體效能統計,協助您快速識別耗時最長的函數。

SELECT * FROM plsql_profiler_show_funclist();

返回結果如下:

                  func_call                  |   func_oid_list    | call_count | us_total | us_declare | us_children | us_self |          time_stamp           
---------------------------------------------+--------------------+------------+----------+------------+-------------+---------+-------------------------------
 oid=0  inline_code_block                    | {0}                |          1 |       24 |         19 |           0 |      24 | 2026-01-05 04:03:37.68941+00
 oid=21721  complex_pkg.calculate_tax()      | {21721}            |          1 |     1309 |          8 |         815 |     494 | 2026-01-05 04:03:37.689697+00
 oid=21721  complex_pkg.calculate_tax()     +| {21721,4294957297} |          1 |      815 |          9 |           0 |     815 | 2026-01-05 04:03:37.690177+00
 oid=4294957297    ->  public.get_tax_rate() |                    |            |          |            |             |         | 
(3 rows)

查看指定函數的行級詳情

當定位到目標函數後,使用plsql_profiler_show_function()可以查看該函數內部每一行代碼的詳細效能資料。

-- 首先,從函數列表中擷取目標函數的OID數組(func_oid_list)
-- 然後,將該OID數組作為參數傳入以下函數
SELECT * FROM plsql_profiler_show_function(ARRAY['...']); -- 請將'...'替換為函數OID列表

樣本

SELECT * FROM plsql_profiler_show_function(ARRAY[21721,4294957297]);

返回結果如下:

 line_number | exec_count | total_time | percent | avg_time | min_time | max_time |                source_code                | time_stamp 
-------------+------------+------------+---------+----------+----------+----------+-------------------------------------------+------------
           0 |          1 |        351 |     100 |      351 |      351 |      351 |  ---- Function Totals ----                | 
           1 |          0 |          0 |       0 |        0 |        0 |        0 | v_rate NUMBER;                            | 
           2 |          1 |        340 |   96.87 |      340 |      340 |      340 |         BEGIN                             | 
           3 |          1 |        338 |    96.3 |      338 |      338 |      338 |             IF p_income <= 50000 THEN     | 
           4 |          0 |          0 |       0 |        0 |        0 |        0 |                 v_rate := 0.10;           | 
           5 |          0 |          0 |       0 |        0 |        0 |        0 |             ELSIF p_income <= 100000 THEN | 
           6 |          1 |         24 |    6.84 |       24 |       24 |       24 |                 v_rate := 0.20;           | 
           7 |          0 |          0 |       0 |        0 |        0 |        0 |             ELSE                          | 
           8 |          0 |          0 |       0 |        0 |        0 |        0 |                 v_rate := 0.30;           | 
           9 |          0 |          0 |       0 |        0 |        0 |        0 |             END IF;                       | 
          10 |          1 |          0 |       0 |        0 |        0 |        0 |             RETURN v_rate;                | 
          11 |          0 |          0 |       0 |        0 |        0 |        0 |         END get_tax_rate;                 | 

查看函數的行級效能資料

使用plsql_profiler_show_funclist()plsql_profiler_show_function()函數可以聯集查詢所有函數內部每一行代碼的詳細效能資料。

SELECT * FROM plsql_profiler_show_funclist() F
CROSS JOIN LATERAL plsql_profiler_show_function(F.func_oid_list) C;

步驟六:產生並查看HTML報告

為了更直觀地分析,您可以使用plsql_profiler_get_report()產生一份完整的HTML格式報告。

-- 在psql用戶端中,使用\o命令將輸出重新導向到檔案
\o plsql_profiler_report.html
-- 開啟僅顯示元組模式,以便輸出純淨的HTML內容
\t 
-- 產生報告
SELECT plsql_profiler_get_report('My Performance Report');
-- 關閉重新導向
\o
-- 關閉僅顯示元組模式
\t 

執行完成後,將返回一個包含完整報告內容的HTML字串。請將該字串複製到HTML檔案中,並在瀏覽器中開啟,以便查看詳盡的效能分析報告。

步驟七:清理資源

分析工作完成後,執行以下操作來重設資料、禁用分析器並移除外掛程式,以避免對後續操作產生效能影響。

-- 1. (可選)重設已採集的分析資料
SELECT plsql_profiler_reset();

-- 2. 禁用分析器
SELECT plsql_profiler_disable();

-- 3. (可選)如果不再需要,可以刪除外掛程式
DROP EXTENSION polar_plsql_profiler;

相關函數參考

下表列出了POLAR_PLSQL_PROFILER外掛程式提供的核心函數。

控制函數

plsql_profiler_enable()

  • 說明:在當前會話中啟用效能分析器。

  • 文法:sys.plsql_profiler_enable() RETURNS bool

  • 傳回值:bool類型。啟用成功返回true,否則返回false

plsql_profiler_disable()

  • 說明:在當前會話中禁用效能分析器。

  • 文法:sys.plsql_profiler_disable() RETURNS bool

  • 傳回值:bool類型。禁用成功返回true,否則返回false

plsql_profiler_reset()

  • 說明:清除當前會話中已收集的所有效能分析資料。

  • 文法:sys.plsql_profiler_reset() RETURNS void

  • 傳回值:無。

報告與分析函數

plsql_profiler_show_funclist()

  • 說明:顯示所有被調用函數的調用鏈和總體效能摘要,不包含分析器自身的函數。

  • 文法:sys.plsql_profiler_show_funclist() RETURNS TABLE(...)

  • 傳回值:返回一個表,包含如下欄位。

    欄位

    說明

    func_call

    函數調用鏈(文本)。

    func_oid_list

    調用棧中的函數OID列表。

    call_count

    函數被調用的次數。

    us_total

    總執行時間(微秒)。

    us_declare

    聲明部分的執行時間(微秒)。

    us_children

    子函數的執行時間(微秒)。

    us_self

    函數自身的執行時間(微秒)。

    time_stamp

    函數調用的時間戳記。

plsql_profiler_show_function()

  • 說明:顯示指定函數內每一行代碼的詳細效能統計。

  • 文法:sys.plsql_profiler_show_function(func_oid OID[]) RETURNS TABLE(...)

  • 參數說明:

    參數

    說明

    func_oid

    要顯示詳細資料的函數OID數組,可從plsql_profiler_show_funclist()func_oid_list列擷取。

  • 傳回值:返回一個表,包含如下欄位。

    欄位

    說明

    line_number

    原始碼中的行號。

    exec_count

    此行被執行的次數。

    total_time

    總執行時間(微秒)。

    percent

    此行在函數總時間中所佔百分比。

    avg_time

    每次執行的平均時間(微秒)。

    min_time

    此行的最小執行時間(微秒)。

    max_time

    此行的最大執行時間(微秒)。

    source_code

    此行的原始碼。

    time_stamp

    執行匿名塊的時間戳記,對於非匿名塊為null

plsql_profiler_get_report()

  • 說明:產生一份完整的HTML格式效能分析報告。

  • 文法:sys.plsql_profiler_get_report(IN title text DEFAULT 'PL/SQL PROFILER REPORT') RETURNS text

  • 參數說明:

    參數

    說明

    title

    報告的標題,選擇性參數,預設為PL/SQL PROFILER REPORT

  • 傳回值:text類型。返回包含完整報告內容的HTML字串。

底層資料擷取函數

plsql_profiler_linestats_local()

  • 說明:擷取原始的行級統計資訊,包括函數執行次數和計時詳情。

  • 文法:sys.plsql_profiler_linestats_local() RETURNS SETOF record

  • 傳回值:返回一個記錄集,包含如下欄位。

    欄位

    說明

    func_oid

    函數OID數組,表示呼叫堆疊。

    line_number

    原始碼中的行號。

    exec_count

    此行被執行的次數。

    total_time

    總執行時間(微秒)。

    percent

    此行在函數總時間中所佔百分比。

    min_time

    此行的最小執行時間(微秒)。

    max_time

    此行的最大執行時間(微秒)。

    source

    此行的原始碼。

    time_stamp

    匿名塊的時間戳記。

plsql_profiler_callgraph_local()

  • 說明:擷取原始的函數調用圖資訊,包括函數調用次數和計時。

  • 文法:sys.plsql_profiler_callgraph_local() RETURNS SETOF record

  • 傳回值:返回一個記錄集,包含如下欄位。

    欄位

    說明

    stack

    函數OID數組,表示呼叫堆疊。

    call_count

    此函數被調用的次數。

    us_total

    總執行時間(微秒)。

    us_declare

    在聲明部分花費的時間(微秒)。

    us_children

    在子函數中花費的時間(微秒)。

    us_self

    在此函數本身中花費的時間(微秒)。

    time_stamp

    函數調用的時間戳記。

plsql_profiler_func_oids_local()

  • 說明:擷取所有被分析過的函數的OID數組。

  • 文法:sys.plsql_profiler_func_oids_local() RETURNS oid[]

  • 傳回值:oid[]類型。返回一個包含所有被採集過資訊的函數OID的數組。

plsql_profiler_funcs_source()

  • 說明:根據函數OID數組返回其原始碼。

  • 文法:sys.plsql_profiler_funcs_source(func_oids oid[]) RETURNS SETOF record

  • 參數說明:

    參數

    說明

    func_oid

    要擷取原始碼的函數OID數組,可從plsql_profiler_linestats_local()func_oid列擷取。

  • 傳回值:返回一個記錄集,包含如下欄位。

    欄位

    說明

    func_oid

    函數OID。

    line_number

    原始碼中的行號。

    source

    此行的原始碼。

plsql_profiler_get_stack()

  • 說明:將函數OID堆棧轉換為函數簽名數組。

  • 文法:sys.plsql_profiler_get_stack(stack oid[]) RETURNS text[]

  • 參數說明:

    參數

    說明

    stack

    函數OID數組,表示呼叫堆疊。可從plsql_profiler_callgraph_local()stack列擷取。

  • 傳回值:text[]類型。返回一個包含函數簽名的文本數組。

plsql_profiler_get_stack_formatted()

  • 說明:將函數OID堆棧轉換為格式化的調用鏈和OID列表。

  • 文法:sys.plsql_profiler_get_stack_formatted(stack oid[]) RETURNS text[]

  • 參數說明:

    參數

    說明

    stack

    函數OID數組,表示呼叫堆疊。可從plsql_profiler_callgraph_local()stack列擷取。

  • 傳回值:text[]類型。返回包含格式化函數調用鏈和OID列表的文本數組。

常見問題

為什麼執行分析函數後看不到任何資料?

請檢查以下幾點:

  1. 您是否在執行目標PL/SQL代碼之前,於同一個會話中執行了SELECT plsql_profiler_enable();。分析器只對啟用後、在當前會話中執行的代碼生效。

  2. 您的資料庫會話是否中斷重連過?分析資料是會話層級的,斷連後會丟失。

可以在生產環境中使用這個工具嗎?

不建議在生產環境中持續開啟。分析器會帶來一定的效能開銷,僅適用於臨時的效能診斷和調優。完成分析後,請務必禁用它。