程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> PHP綜合 >> 通過緩存數據庫結果提高PHP性能

通過緩存數據庫結果提高PHP性能

編輯:PHP綜合

眾所周知,緩存數據庫查詢的結果可以顯著縮短腳本執行時間,並最大限度地減少數據庫服務器上的負載。如果要處理的數據基本上是靜態的,則該技術將非常有效。這是因為對遠程數據庫的許多數據請求最終可以從本地緩存得到滿足,從而不必連接到數據庫、執行查詢以及獲取結果。

但當您使用的數據庫與 Web 服務器位於不同的計算機上時,緩存數據庫結果集通常是一個不錯的方法。不過,根據您的情況確定最佳的緩存策略卻是一個難題。例如,對於使用最新數據庫結果集比較重要的應用程序而言,時間觸發的緩存方法(緩存系統常用的方法,它假設每次到達失效時間戳記時就重新生成緩存)可能並不是一個令人滿意的解決方案。這種情況下,您需要采用一種機制,每當應用程序需要緩存的數據庫數據發生更改時,該機制將通知該應用程序,以便該應用程序將緩存的過期數據與數據庫保持一致。這種情況下使用“數據庫更改通知”將非常方便。

“數據庫更改通知”入門

“數據庫更改通知”特性的用法非常簡單:創建一個針對通知執行的通知處理程序 – 一個 PL/SQL 存儲過程或客戶端 OCI 回調函數。然後,針對要接收其更改通知的數據庫對象注冊一個查詢,以便每當事務更改其中的任何對象並提交時調用通知處理程序。通常情況下,通知處理程序將被修改的表的名稱、所做更改的類型以及所更改行的行 ID(可選)發送給客戶端監聽程序,以便客戶端應用程序可以在響應中執行相應的處理。

為了了解“數據庫更改通知”特性的作用方式,請考慮以下示例。假設您的 PHP 應用程序訪問 OE.ORDERS 表中存儲的訂單以及 OE.ORDER_ITEMS 中存儲的訂單項。鑒於很少更改已下訂單的信息,您可能希望應用程序同時緩存針對 ORDERS 和 ORDER_ITEMS 表的查詢結果集。要避免訪問過期數據,您可以使用“數據庫更改通知”,它可讓您的應用程序方便地獲知以上兩個表中所存儲數據的更改。

您必須先將 CHANGE NOTIFICATION 系統權限以及 EXECUTE ON DBMS_CHANGENOTIFICATION 權限授予 OE 用戶,才能注冊對 ORDERS 和 ORDER_ITEMS 表的查詢,以便接收通知和響應對這兩個表所做的 DML 或 DDL 更改。為此,可以從 SQL 命令行工具(如 SQL*Plus)中執行下列命令。

CONNECT / AS SYSDBA;
GRANT CHANGE NOTIFICATION TO oe;
GRANT EXECUTE ON DBMS_CHANGE_NOTIFICATION TO oe;

確保將 init.ora 參數 job_queue_processes 設置為非零值,以便接收 PL/SQL 通知。或者,您也可以使用下面的 ALTER SYSTEM 命令:

ALTER SYSTEM SET "job_queue_processes"=2;

然後,在以 OE/OE 連接後,您可以創建一個通知處理程序。但首先,您必須創建將由通知處理程序使用的數據庫對象。例如,您可能需要創建一個或多個數據庫表,以便通知處理程序將注冊表的更改記錄到其中。在以下示例中,您將創建 nfresults 表來記錄以下信息:更改發生的日期和時間、被修改的表的名稱以及一個消息(說明通知處理程序是否成功地將通知消息發送給客戶端)。

CONNECT oe/oe;
CREATE TABLE nfresults (
operdate DATE,
tblname VARCHAR2(60),
rslt_msg VARCHAR2(100)
);

在實際情況中,您可能需要創建更多表來記錄通知事件以及所更改行的行 ID 等信息,但就本文而言,nfresults 表完全可以滿足需要。

使用 UTL_HTTP 向客戶端發送通知

您可能還要創建一個或多個 PL/SQL 存儲過程,並從通知處理程序中調用這些存儲過程,從而實現一個更具可維護性和靈活性的解決方案。例如,您可能要創建一個實現將通知消息發送給客戶端的存儲過程。“清單 1”是 PL/SQL 過程 sendNotification。該過程使用 UTL_HTTPPL 程序包向客戶端應用程序發送更改通知。

清單 1. 使用 UTL_HTTP 向客戶端發送通知

CREATE OR REPLACE PROCEDURE sendNotification(url IN VARCHAR2,
tblname IN VARCHAR2, order_id IN VARCHAR2) IS
req  UTL_HTTP.REQ;
resp UTL_HTTP.RESP;
err_msg VARCHAR2(100);
tbl VARCHAR(60);
BEGIN
tbl:=SUBSTR(tblname, INSTR(tblname, '.', 1, 1)+1, 60);
BEGIN
req := UTL_HTTP.BEGIN_REQUEST(url||order_id||'&'||'table='||tbl);
resp := UTL_HTTP.GET_RESPONSE(req);
INSERT INTO nfresults VALUES(SYSDATE, tblname, resp.reason_phrase);
UTL_HTTP.END_RESPONSE(resp);
EXCEPTION WHEN OTHERS THEN
err_msg := SUBSTR(SQLERRM, 1, 100);
INSERT INTO nfresults VALUES(SYSDATE, tblname, err_msg);
END;
COMMIT;
END;
/

如“清單 1”所示,sendNotification 以 UTL_HTTP.BEGIN_REQUEST 函數發出的 HTTP 請求的形式向客戶端發送通知消息。此 URL 包含 ORDERS 表中已更改行的 order_id。然後,它使用 UTL_HTTP.GET_RESPONSE 獲取客戶端發出的響應信息。實際上,sendNotification 並不需要處理客戶端返回的整個響應,而是只獲取一個在 RESP 記錄的 reason_phrase 字段中存儲的簡短消息(描述狀態代碼)。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved