2011-01-13 42 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); 

?>