php+mysql缓存技术的实现
本教程适合于那些对缓存SQL查询以减少数据库连接与执行的负载、提高脚本性能感兴趣的PHP程序员。
概述
许多站点使用数据库作为站点数据存储的容器。数据库包含了产器信息、目录结构、文章或者留言本,有些数据很可能是完全静态的,这些将会从一个缓存系统中得到的极大好处。
这样一个系统通过把SQL查询的结果缓存到系统的一个文件中存储,从而阻止连接数据库,构造查询与取得返回结果而提高了响应时间。
有些系统数据库并不是放在WEB服务器上的,这样需要一个远程连接(TCP或者其它类似的),或者从数据库中获取大量的数据,这样你得忍受更多时间,这决定于系统响应时间与资源利用。
前提
本教程使用MySQL作为数据库。你需要安装MySQL(www.mysql.com下载是有效的)和激活PHP MYSQL扩展(默认情况是激活的)。
由于要查询数据库,你需要知识一些SQL(结构化查询语言)的基本常识。
缓存SQL查询结果
为什么要缓存查询结果?
缓存查询结果能极大地改进脚本执行时间和资源需求。
缓存SQL查询结果也允许你通过后期处理数据。如果你用文件缓存去存储全部脚本的输出结果(HTML输出),这样可能是行不通的。
当你执行一个SQL查询时,点典的处理过程是:
<!--[if !supportLists]-->l <!--[endif]-->连接数据库
<!--[if !supportLists]-->l <!--[endif]-->准备SQL查询
<!--[if !supportLists]-->l <!--[endif]-->发送查询到数据库
<!--[if !supportLists]-->l <!--[endif]-->取得返回结果
<!--[if !supportLists]-->l <!--[endif]-->关闭数据库连接
以上方法非常占用资源并且相反的影响了脚本的性能。只能通过取得的大量返回数据和数据库服务器的位置这二个要素来相互协调。尽管持续连接可以改进连接数据库时的负载,但非常耗费内存资源,如果获取的是大量的数据,那么存储的全部时间会非常短暂。
创建一条SQL查询:
SQL(结构化查询语言)查询被用作操作数据库及它内容的接口。SQL可用于定义和编辑表的结构,插入数据到表,更新或删除表中的信息。
SQL是用于与数据通讯的语言,在大多数PHP数据库扩展(MySQL,ODBC,Oracle等)通过传递SQL查询到数据库中来管理整个过程。
本教程中,仅仅用select语言来获取数据库中的数据。这些数据将被缓存,之后将用作数据源。
决定什么时候更新缓存:
根据程序的需要,缓存可以采取多种形式。最常见的3种方式是:
<!--[if !supportLists]-->l <!--[endif]-->时间触发缓存(过期的时间戳)
<!--[if !supportLists]-->l <!--[endif]-->内容改变触发缓存(发现数据改变后,相应地更新缓存)
<!--[if !supportLists]-->l <!--[endif]-->人工触发缓存(人工的方式告知系统信息超期并且强制产生新的缓存)
你的缓存需求可能是以上原理的一个或多个的综合。本教程将讨论时间触发方式。然而,在一个全面的缓存机制中,3种方式的综合将被使用。
缓存结果:
基本的缓存是用PHP的两个函数serialize()和unserialize()(译注:这二个函数分别代表序列化与反序列化)。
函数serialize()用于存储PHP的值,它能保证不失去这些值的类型和结构。
事实上,PHP的session扩展是用序列化过的变量,把session变量($_SESSION)存储在系统的一个文件中。
函数unserialize()与以上操作相反并且使序列化过的字符串返回到它原来的结构和数据内容。
在本例中,以一个电子商务商店为例。商店有2个基本表,categories和products(此处为原始数据库表名).product表可能每天都在变化,categories仍然是不变静止的。
要显示产品,你可以用一个输出缓存脚本来存储输出的HTML结果到一个文件中。然而categories表可能需要后期处理。例如,所有的目录通过变量 category_id(通过$_REQUEST['category_id']来取得)被显示,你可能希望高亮当前被选择的目录。
表categories结构
Field Type Key Extra
category_id int(10) unsigned PRI auto_incremen
category_name varchar(255)
category_description text
在本例中,通过时间触发缓存技术被运用,设定一段时间后让其缓存SQL输出过期。在此特殊的例子中,定一段时间为24小时。
序列化例子:
<!--[if !supportLists]-->l <!--[endif]-->连接数据库
<!--[if !supportLists]-->l <!--[endif]-->执行查询
<!--[if !supportLists]-->l <!--[endif]-->取得所有结果构成一个数组以便后面你可以访问
<!--[if !supportLists]-->l <!--[endif]-->序列化数组
<!--[if !supportLists]-->l <!--[endif]-->保存序列化过的数组到文件中*/
$file = 'sql_cache.txt';
$link = mysql_connect('localhost','username','password') or die (mysql_error());
mysql_select_db('shop') or die (mysql_error());
/* 构造SQL查询 */
$query = "SELECT * FROM categories";
$result = mysql_query($query) or die (mysql_error());
while ($record = mysql_fetch_array($result) ){
$records[] = $record;
}
$OUTPUT = serialize($records);
$fp = fopen($file,"w"); // 以写权限的方式打开文件
fputs($fp, $OUTPUT);
//fwrite($fp,$OUTPUT);
fclose($fp);
/*查看sql_cache.txt文件,里面的内容可能类似这样的:
a:1:{i:0;a:6:{i:0;s:1:"1";s:11:"category_id";s:1:"1";i:1;s:9:"Computers";s:13:"category_name";s:9:"Computers" ;i:2;s:25:"Description for computers";s:20:"category_description";s:25:"Description for computers";}}
这个输出是它的变量和类型的内部表现形式。假若你用mysql_fetch_array()函数返回数字索引的数组和一个关联的数组(这就是为什么数据看起来像是发生了两次),一个是数字索引,另一个是字符串索引。
使用缓存:
要用缓存,你需要用函数unserialize()来使数据还原成原始格式与类型。
你可以用file_get_contents()这个函数来读取sql_cache.txt文件的内容,把它赋给一个变量。
请注意:这个函数在PHP4.3.0及以上版本有效。若你使用的是一个老版本的PHP,一个简单的方法是用file()函数(读整个文件到一个数组,每行变成一个数组)。implode()函数用于把数组的各元素连接成一个字符串然后使用unserialize()反序列化。*/
// file_get_contents() 适合于for PHP < 4.3.0
$file = 'sql_cache.txt';
$records = unserialize(implode('',file($file)));
//现在你可以通过$records数组并且取得原始查询的数据:
foreach ($records as $id=>$row) {
print $row['category_name']."<br>";
}
/* 注意$records是数组(一个包含了查询结果的数字索引列——每行是一个数字和一个字符串...真是混乱)的一排。
把它们放在一块:
基于本例子中的时间来决定是否缓存。如果文件修改的时间戳比当前时间戳减去过期时间戳大,那么就用缓存,否则更新缓存。
<!--[if !supportLists]-->l <!--[endif]-->检查文件是否存在并且时间戳小于设置的过期时间
<!--[if !supportLists]-->l <!--[endif]-->获取存储在缓存文件中的记录或者更新缓存文件
$file = 'sql_cache.txt';*/
$expire = 86400; // 24 小时 (单位:秒)
if (file_exists($file)&&filemtime($file) > (time() - $expire)){
// 取得缓存中的记录
$records = unserialize(file_get_contents($file));
} else {
// 通过 serialize() 函数创建缓存
}
/*附加其它可能的:
<!--[if !supportLists]-->l <!--[endif]-->把缓存结果存储在共享内存中以获取更快的速度
<!--[if !supportLists]-->l <!--[endif]-->增加一个功能随机地运行SQL查询并且检查是否输出与缓存输出一致。如果不一致,则更新缓存(本函数运行次数的概率可以定为1/100)。通过哈希算法(如MD5())可以协助判断字符串或者文件是否改变。
<!--[if !supportLists]-->l <!--[endif]-->增加一个管理员的功能,人工的删除这个缓存文件,以强制更新缓存(如file_exists()函数返回 false时)。你可以用函数unlink()删除文件。
脚本:*/
$file = 'sql_cache.txt';
$expire = 86400; // 24 小时
if (file_exists($file)&&filemtime($file) > (time() - $expire)) {
$records = unserialize(file_get_contents($file));
//$records=unserialize(fread($file,filesize($file)));
} else {
$link = mysql_connect('localhost','username','password') or die (mysql_error());
mysql_select_db('shop') or die (mysql_error());
/* 构造SQL查询 */
$query = "SELECT * FROM categories";
$result = mysql_query($query) or die (mysql_error());
while ($record = mysql_fetch_array($result) ) {
$records[] = $record;
}
$OUTPUT = serialize($records);
$fp = fopen($file,"w");
//fputs($fp, $OUTPUT);
fwrite($fp,$OUTPUT);
fclose($fp);
} // end else
// 查询结果在数组 $records 中
foreach ($records as $id=>$row) {
if ($row['category_id'] == $_REQUEST['category_id']) {
// 被选择的目录显示粗体字
print '<B>'.$row['category_name'].'</B><BR>';
} else {
// 其它目录显示用常规字体
print $row['category_name'].'<br>';
}
} // end foreach
php+mysql缓存技术的实现的更多相关文章
- php缓存技术总结
缓存是指临时文件交换区,电脑把最常用的文件从存储器里提出来临时放在缓存里,就像把工具和材料搬上工作台一样,这样会比用时现去仓库取更方便.因为缓存往往使用的是RAM(断电即掉的非永久储存), ...
- 网站缓存技术总结( ehcache、memcache、redis对比)
网站技术高速发展的今天,缓存技术已经成为大型网站的一个关键技术,缓存设计好坏直接关系的一个网站访问的速度,以及购置服务器的数量,甚至影响到用户的体验. 网站缓存按照存放的地点不同,可以分为客户端缓存. ...
- PHP网页缓存技术
http://blog.sina.com.cn/s/blog_646e51c40100weu9.html 前台静态化:把动态页面解析后保存为静态页面 文件缓存:把查询结果保存为文件,XML 内存缓存: ...
- ThinkPHP的缓存技术
原文:ThinkPHP的缓存技术 如果没有缓存的网站是百万级或者千万级的访问量,会给数据库或者服务器造成很大的压力,通过缓存,大幅减少服务器和数据库的负荷.假如我们 把读取数据的过程分为三个层,第一个 ...
- 详细讲解PHP中缓存技术的应用
PHP,一门最近几年兴起的web设计脚本语言,由于它的强大和可伸缩性,近几年来得到长足的发展,php相比传统的asp网站,在速度上有绝对的优势,想mssql转6万条数据php如需要40秒,asp不下2 ...
- PHP缓存技术的多种方法小结
这里所说的数据缓存是指数据库查询PHP缓存机制,每次访问页面的时候,都会先检测相应的缓存数据是否存在,如果不存在,就连接数据库,得到数据,并把查询结果序列化后保存到文件中,以后同样的查询结果就直接从缓 ...
- ThinkPHP 缓存技术详解 使用大S方法
如果没有缓存的网站是百万级或者千万级的访问量,会给数据库或者服务器造成很大的压力,通过缓存,大幅减少服务器和数据库的负荷,假如我们把读取数据的过程分为三个层,第一个是访问层,第一个是缓存层,第三个是数 ...
- MySQL缓存参数优化(转)
MySQL 数据库性能优化之缓存参数优化 数据库属于 IO 密集型的应用程序,其主要职责就是数据的管理及存储工作.而我们知道,从内存中读取一个数据库的时间是微秒级别,而从一块普通硬盘上读取一个IO是在 ...
- java缓存技术的介绍
一.什么是缓存1.Cache是高速缓冲存储器 一种特殊的存储器子系统,其中复制了频繁使用的数据以利于快速访问2.凡是位于速度相差较大的两种硬件/软件之间的,用于协调两者数据传输速度差异的结构,均可称之 ...
随机推荐
- 转:Python 文本挖掘:使用gensim进行文本相似度计算
Python使用gensim进行文本相似度计算 转于:http://rzcoding.blog.163.com/blog/static/2222810172013101895642665/ 在文本处理 ...
- 【转】Oracle 查询库中所有表名、字段名、表名说明、字段名说明
转自 :http://gis-conquer.blog.sohu.com/170243422.html 查询所有表名:select t.table_name from user_tables t; 查 ...
- SQL中的替换函数replace()使用
语法REPLACE ( string_expression , string_pattern , string_replacement ) 参数string_expression 要搜索的字符串表达式 ...
- 【2016北京集训】Mushroom
Portal --> broken qwq Description 一开始有个蘑菇,蘑菇里面有\(n\)个房间,是一棵有根树,\(1\)号是根,每个房间里面都有杂草,现在要支持以下操作:将某个指 ...
- 【CF123E】Maze
Portal --> cf123E Solution 首先步数的话可以转化成每条边经过了几次这样来算 假设现在确定了起点\(S\)和终点\(T\),我们将\(T\)看成树根,那么考虑边\((u, ...
- 框架----Django之Form提交验证(二)
一.Form提交验证之(学生表.老师表.班级表)的添加和编辑实现案例 1. 浏览器访问 http://127.0.0.1:8000/student_list/ http://127.0.0.1:800 ...
- zlib解压缩gzip
zlib是个著名的开源解压缩库,gzip是一种压缩文件格式. zlib可以压缩原始数据并输出gzip文件,gzip文件中除了压缩数据外,还有描述这些数据的文件头,所以当原始数据较小时,会出现zlib的 ...
- selenium利用Excel进行参数化(简单示例)
上篇搭建好环境后,正真开始我的自动化之旅了.... 开始之前特别说明一下testNG的版本,不能直接使用Eclipse直接线上下载的版本,线上版本太高,不能兼容,运行程序会报以下错误,需要自行下载低一 ...
- 51nod 1629 B君的圆锥
1629 B君的圆锥 基准时间限制:1 秒 空间限制:131072 KB 分值: 10 难度:2级算法题 收藏 关注 B君要用一个表面积为S的圆锥将白山云包起来. B君希望包住的白山云体积尽量 ...
- 维护后面的position + 离线 + 线段树 bzoj 3585
3585: mex Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 918 Solved: 481[Submit][Status][Discuss] ...