Technical support2007/05/02 18:48
views: 1037 times
超大字體(180%)放大字體(130%)原始字體(100%)

這個東西也不是甚麼新奇的玩意,主要是從 ADODB 這個套件上看到的,所以就自己實作了一個類似的東西。畢竟,對於自行開發的網站系統而言,ADODB 固然有他的好處,不過,龐大的程序有時候卻很令人厭煩。加上,我這種不喜歡使用套件的個性…(總而言之就是自己龜毛,說這麼多廢話做啥 orz)

PHP 提供了一個很好用的 function, 針對於我們的目的來說:

1. 把 Query 所輸出的結果轉換為可以儲存的物件
2. 能夠將此物件互相轉換,卻不改變其原來的型態

OK, 目的就是這麼簡單。在此我們使用自行開發的 class 來做應用。步驟如下:

1. 監聽 mysql_query,過濾出 select 的 query 指令。
2. 對 select 指令所 query 出來的結果,使用 serialize/unserialize 儲存於自訂的檔案中。
3. 設定一個 cache flush time, 時間到了就從新存取一次 cache file。
4. 對於每次的 query, 若是在 cache flush time 內,就讀取檔案內容丟給前端顯示,不對 sql 做檢索。

以上就是我的步驟,至於方式與流程如何操作,就看個人了。接著,舉出一些實例的 code 來說明。

// 這是一個自訂的 class, 其中包含了 mysql 的連線與其他動作
class mysql_DB {

var $CacheDir = “/var/www/html/mysqlcache/”;
// 檢查是否做了快取
function checkCache($sql, $caching=false)
{
$cacheQueryFullPathFile = $this->CacheDir.md5($sql).”.cache”;
if(is_file($cacheQueryFullPathFile)) {
$factime = fileactime($cacheQueryFullPathFile);
if(time() - $factime > $cachereflush) $caching = true;
} else {
$caching = true;
}
return $caching;
}
// 實作快取的地方
function cacheSQL($sql, $sqlArray=array(), $caching=false)
{
$cacheQueryFullPathFile = $this->CacheDir.md5($sql).”.cache”;
if($caching==true)
{
$__cache = serialize($sqlArray);
if(!is_file($cacheQueryFullPathFile)) @touch($cacheQueryFullPathFile);
$fp = @fopen($cacheQueryFullPathFile, “r+”);
// 我使用了 mb_strlen 計算長度,是因為 UTF-8 的關係
if(!fwrite($fp, $__cache, mb_strlen($__cache))
{
$this->halt(”Cache file writting error!”); // 自訂的錯誤控制
}
@fclose($fp);
$dataArray = false; // 最後傳回值,使用 false 是因為它不需要傳回
} else {
$fp = @fopen($cacheQueryFullPathFile, “r”);
$__cache = fread($fp, filesize($cacheQueryFullPathFile));
@fclose($fp);
$dataArray = unserialize($__cache);
}
return $dataArray;
}

到此,以上是一個簡單的 class, 如何變換看個人,這兩個 function 是檢查與建立快取檔案用,接下來,針對 php 的程式中呼叫 mysql_query 的地方做改善。

// 這是將 mysql 呼叫應用函式製作成一個 class, 我習慣分開做,上面那一個只包含簡易原生 php mysql 指令,複雜應用放此。
class mydb {

// 這個 function 專門用來操作 mysql 的原生指令
function get_Sql($sql)
{
global $mysql_DB;
if(empty($sql)) return false;
// 若沒有 cache, 且為 select 的 query
if($mysql_DB->checkCache($sql)==false && preg_match(”/^select/i”, $sql))
{
$data = $mysql_DB->cacheSQL($sql, false);
} else {
$result = $mysql_DB->query($sql);
$data = $mysql_DB->fetch_array($result);
if(preg_match(”/^select/i”, $sql)) $mysql_DB->cacheSQL($sql, $data, true);
}
return $data;
}
}

接著,在 php 呼叫 mysql 的函式,就是這樣…

$query = “SELECT * FROM mydata WHERE id=’1′”;
$result = $mydb->get_Sql($query);

以上,就是個簡單的快取範例。對於降低 mysql 的存取來說,也有相當程度上的助益。以空間換取時間,或許這樣的方法也是一種,就端看個人怎麼去應用它了。當然啦,PHP 5 在 OO 的應用上還算頗強大的(應該啦),所以說,把整個 class 組裝成一個完善的 OO 來使用,就會更方便了。只是,不巧我的工作平台是 PHP 4… 實在是沒有力氣把它包得很漂亮,所以就這樣將就將就啦 (笑)

ps. 請不要對亂數取值的 query 作快取,不然你會發現效能不升反降喔 XDD

創用 CC 授權
Creative Commons License
本創作適用 姓名標示-非商業性-禁止改作 3.0 創用 CC 授權,台灣並依循所適用的授權條款。

Bookmarks  HEMiDEMi  Technorati  Del.icio.us  Digg  funP  Yahoo!  Furl
Writer profile
author image
偏執與強迫症的患者,算不上是無可救藥,只是我已經遇上我的良醫了。
Posted by hina

Trackback URL : http://hina.ushiisland.net/blog/hinablue/trackback/247

Leave your greetings.

[登入][OpenID是?]