2011-01-13 66 views
0

我的第一个问题,我希望我会做得很好。将多个sql查询转换为一个大型数组

我正在另一个人写的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

“我真的改善这种代码在性能方面?”您需要自己测试一下 - 在您的更改前后使用实际工作负载对性能进行基准测试。 – 2011-01-13 13:43:50

回答

0

我会说你最有可能不应该碰它。有两个原因。

  1. 数据库语句很快。这就是数据库的全部内容。使用唯一索引,来自数据库表的SELECT会从硬盘读取非常有限的数据量(或者甚至可能是内存中的数据库缓存)。根据对数据库的访问(本地,远程),它应该非常快或者闪电般快。除非你有一个糟糕的网络。

  2. 您将代码添加到项目中。增加的代码意味着错误的可能性。尽管“旧”例程确实工作正常,并且没有明显的性能问题(至少您并未声明因为性能不佳而需要更改),但您的代码将是新的,未经测试的,并且很可能包含错误和/或通过这个数组进行糟糕的搜索。除此之外,像索引数据一样在内存中搜索未索引的数据比索引数据中的索引慢得多,而且你很可能会损害性能。

+0

好吧,这是一个尚未完成的项目,我被要求改进其性能,这就是为什么我必须决定是否更改代码。我认为关键是“另外一个事实是,对像索引数据这样的未索引数据进行内存内搜索比搜索索引数据慢得多,而且你很可能会损害性能。”我想这就是我需要知道的。 无论如何,我会尝试改变它并对两个代码进行基准测试,因为数据库在另一个主机中。谢谢! – mariogl 2011-01-13 20:36:31

0

我想说,这取决于你的基础设施。

如果您在与应用程序相同的主机上运行MySQL,它可能不会提高性能,甚至不会伤害它。

只需在您的确切环境中进行测试即可。

我写了一篇关于减少网络延迟的文章。尽管Oracle具体,一些方法也将适用于MySQL:http://blog.fatalmind.com/2009/12/22/latency-security-vs-performance/

+0

好文章,谢谢。 – mariogl 2011-01-13 20:48:06

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); 

?>