某生產環境的 DB Server CPU 持續維持在 100%,vmstat 輸出也異常偏高。經排查鎖定到一條高耗 CPU 的 SQL,發現其呼叫了一個將 IP 字串轉換為數值的 PL/SQL 自訂函數。將該邏輯移至資料庫外層的 VB 程式實作後,CPU 使用率大幅下降,問題隨即解決。
該函數邏輯本身並不複雜,亦未存取任何資料庫物件,卻造成驚人效能衝擊。結論明確:與資料庫核心業務無關的處理過程,應移至呼叫端應用程式實作,即便 SQL 程序能實現也應避免。
以下範例說明錯誤與正確寫法的效能差異:
CREATE OR REPLACE FUNCTION fn_ipaddr_to_province (p_ipaddr NUMBER)
RETURN VARCHAR2
IS
v_ret VARCHAR2(100) := '';
BEGIN
BEGIN
SELECT province
INTO v_ret
FROM ipdb
WHERE start_ip <= p_ipaddr AND end_ip >= p_ipaddr AND ROWNUM = 1;
EXCEPTION
WHEN NO_DATA_FOUND THEN v_ret := '';
END;
RETURN v_ret;
EXCEPTION
WHEN OTHERS THEN RAISE;
END fn_ipaddr_to_province;
/
BEGIN
SELECT serverip
INTO v_serverip
FROM domainname
WHERE province = fn_ipaddr_to_province(p_ip) AND ROWNUM = 1;
EXCEPTION
WHEN NO_DATA_FOUND THEN v_serverip := 'mp3.u-vv.com';
END;
v_province := fn_ipaddr_to_province(p_ip);
BEGIN
SELECT serverip
INTO v_serverip
FROM domainname
WHERE province = v_province AND ROWNUM = 1;
EXCEPTION
WHEN NO_DATA_FOUND THEN v_serverip := 'default domain';
END;
此案例再次印證:資料庫專注於資料存取與集合運算,業務運算交給應用層,才是高效能架構的正解。