我的第一个问题,我希望我能做好。
我正在使用另一个人写的PHP Web引擎。这段代码会进行大量的数据库调用。例如,要编写一个html标记,它会对数据库进行三次调用:一个用于询问文件名,另一个用于标题,另一个用于alt属性,即使title和alt位于同一个数据库字段中。
为了改进这段代码,我正在尝试进行一次初始调用,它会带来我需要的所有信息并将其保存到数组中。由于我的初始调用使用了几个连接,我使用的是二维数组,以便更好地理解:
SELECT a.*, b.*, c* FROM a INNER JOIN b ON... ... INNER JOIN c ON...
我将结果保存在二维数组中:
$info["a"]["field1"], $info["a"]["field2"], ...
$info["b"]["field1"], $info["b"]["field2"], ...
$info["c"]["field1"], $info["c"]["field2"], ...
因此,每次我需要数据时,我都会搜索此数组而不是进行数据库调用。
我的问题是:鉴于我从一个大的多重查询开始,然后我使用一个大的二维数组,我真的在性能方面改进了这个代码吗?
感谢。
答案 0 :(得分:0)
我说这取决于你的基础设施。
如果您在与应用程序相同的主机上运行MySQL,则可能无法提高性能,甚至可能会损害它。
只需在您的确切环境中进行测试。
我写了一篇关于减少网络延迟的文章。虽然Oracle具体,但某些方法也适用于MySQL:http://blog.fatalmind.com/2009/12/22/latency-security-vs-performance/
答案 1 :(得分:0)
我说你最有可能不应该碰它。有两个原因。
数据库语句很快。这就是数据库的全部意义所在。使用唯一索引,来自数据库表的SELECT从硬盘(或者甚至可能是内存中的数据库缓存)读取非常有限的数据量。根据对数据库(本地,远程)的访问,它应该非常快或快速。除非你网络不好。
您可以向项目添加代码。添加代码意味着错误的可能性。虽然“旧”例程确实可以正常工作并且您没有明显的性能问题(至少您没有声明要因为性能低而需要更改),但您的代码将是新的,未经测试且很可能包含错误和/或通过此数组执行不佳的搜索。除此之外,对数据之类的无索引数据进行内存中搜索比在索引数据中搜索要慢得多,而且很可能会损害性能。
答案 2 :(得分:0)
在大型数据库中进行联接查询会占用大量查询时间。创建一个巨型阵列并不是解决方案,因为声明巨型阵列并且在每次运行中仅使用少量条目是多余的。
你要找的是memcache。 Memcache就像服务器ram上的数组一样工作。 Php不会声明数组并每次都缓存它。相反,memcache将数据保存在ram中,随时可用。您可以在memcache中设计基于id的定义并使用它。
我的建议是声明一个扩展数组类的对象。如果数据位于缓存中,您可以重载构造函数以检索数据。如果没有,它应该从数据库中获取数据并添加到memcache。
只要您定义了数据,数据就会在缓存中。
尽量不要制造巨型阵列。
http://php.net/manual/en/book.memcache.php
这是我一直在使用的课程。如果您有包含常量数据的表,我建议您使用带有88000秒时间限制的cacheTable方法并添加一个cronjob以便每天重新缓存它。
<?php
class mc extends ArrayObject{
var $mc_obj;
function __construct(){
$this->mc_obj = new Memcache;
$this->mc_obj->connect("127.0.0.1",11211);
# You might need to set "127.0.0.1" to "localhost"
}
function fetch($table,$id){
/*
if the n-th row of the $table is not in the cache, cache it
return the row.
*/
if(!$this->mc_obj->get($table."_".$id)){
$this->cacheById($table,$id);
}
return $this->mc_obj->get($table."_".$id);
}
/*
numeric is the boolean for mysql_fetch type.
if true the the array will be created numeric with mysql_fetch_row
else the array will be created associative with mysql_fetch_assoc
*/
function cacheTable($table,$numeric=false,$conditions="1",$idFieldOfTable="id",$cacheTimeLimit=120){
$q1 = mysql_query("select * from `".$table."` where ".$conditions.";");
if($numeric){
while($row = mysql_fetch_row($q1)){
$this->mc_obj->set($table."_".$row[0],$row,false,$cacheTimeLimit);
}
}
else{
while($row = mysql_fetch_assoc($q1)){
$this->mc_obj->set($table."_".$row[$idFieldOfTable],$row,false,$cacheTimeLimit);
}
}
}
function cacheById($table,$id,$numeric=false,$idFieldOfTable="id",$cacheTimeLimit=120){
$q1 = mysql_query("select * from `".$table."` where `".$idFieldOfTable."`=".$id." Limit 1;");
if($numeric){
$row = mysql_fetch_row($q1);
}
else{
$row = mysql_fetch_assoc($q1);
}
$this->mc_obj->set($table."_".$id,$row,false,$cacheTimeLimit);
}
public function offsetGet($key) {
$id = substr($key,strrpos($key,"_")+1);
$table = substr($key,0,strrpos($key,"_"));
return $this->fetch($table,$id);
/*
By overriding this method you will be able to call any particular cell like
$cell = $memCacheObject['tableName_Rowid']['field'];
*/
}
}
?>
以下是如何使用它:
<?php
mysql_connect("localhost","root","");
mysql_select_db("DB_NAME");
$db = new mc();
$table = "city";
$id = 3;
$a = $db->fetch($table,$id);
// $a is the associative row array
$b = $db->fetch($table,$id);
// $b is the numeric row array
$cell = $db['city_18']['name'];
//$cell is the name of the city with id 18 in the city table
//in order to cache the whole table
$db->cacheTable("city",false,"1","id",90000);
?>