2011-01-27 81 views
2

我在我的项目中使用了Zend Framework。我需要插入多个记录,并且发现Zend_Db在my_sql查询(多次)中出人意料地比较慢,这让我觉得我做错了什么。 这里有两个例子。为什么Zend_Db_Adapter比mysql_query慢得多

Zend_Db_Adapter会:

 $startTime = microtime(true); 
     $db = Zend_Db_Table::getDefaultAdapter(); 
     $db->beginTransaction(); 

     $dateAdded = date('Y-m-d H:i:s'); 
     $lastChanged = $dateAdded;     

     foreach ($importDataNamespace->data as $subscriberNum => $subscriber) 
     { 
      foreach ($fieldsMap as $fieldNumber => $fieldTag) { 
       if (isset($subscriber[$fieldNumber])) { 
        $subscriberData[$fieldTag] = $subscriber[$fieldNumber]; 
       } else { 
        $subscriberData[$fieldTag] = ''; 
       } 
      } 
      $query = 'INSERT INTO subscribers (list_id, account_id, email_address, first_name, last_name, date_added, last_changed) ' . 
        'VALUES (' . 52 . ', ' . 29 . ', ' . $db->quote($subscriberData['EMAIL']) . ', ' . $db->quote($subscriberData['FNAME']) . 
        ', ' . $db->quote($subscriberData['LNAME']) . ', ' . $db->quote($dateAdded) . ', ' . $db->quote($lastChanged) . ')'; 
      $db->query($query);                 
     } 
     $db->commit(); 

     $this->view->time = microtime(true) - $startTime; 

实施例与的mysql_query:

 $startTime = microtime(true); 

     $user = 'root'; 
     $password = 'password'; 
     $db = 'database'; 
     $connect = @mysql_connect('localhost',$user,$password) or die("Failed to connect database"); 
     @mysql_select_db($db) or die("Failed to select database");   

     $dateAdded = date('Y-m-d H:i:s'); 
     $lastChanged = $dateAdded;  

     $result = mysql_query('SET autocommit = 0');    

     foreach ($importDataNamespace->data as $subscriberNum => $subscriber) 
     { 
      foreach ($fieldsMap as $fieldNumber => $fieldTag) { 
       if (isset($subscriber[$fieldNumber])) { 
        $subscriberData[$fieldTag] = $subscriber[$fieldNumber]; 
       } else { 
        $subscriberData[$fieldTag] = ''; 
       } 
      } 
      $query = 'INSERT INTO subscribers (list_id, account_id, email_address, first_name, last_name, date_added, last_changed) ' . 
       'VALUES (' . 52 . ', ' . 29 . ', \'' . mysql_real_escape_string($subscriberData['EMAIL']) . '\', \'' . mysql_real_escape_string($subscriberData['FNAME']) . 
       '\', \'' . mysql_real_escape_string($subscriberData['LNAME']) . '\', \'' . $dateAdded . '\', \'' . $lastChanged . '\')';      
      mysql_query($query);          
     } 
     $result = mysql_query('SET autocommit = 1'); 
     $result = mysql_query('COMMIT;'); 

     $this->view->time = microtime(true) - $startTime;   

在第一种情况用了14.8秒,在第二3.7。 你能告诉我为什么它会发生,你做错了什么?

如果我删除任何报价Zend_Db的需要12秒内从14报价,但它仍然远远超过用的mysql_query慢:

 $startTime = microtime(true); 
     $db = Zend_Db_Table::getDefaultAdapter(); 
     $db->beginTransaction(); 

     $dateAdded = date('Y-m-d H:i:s'); 
     $lastChanged = $dateAdded;     

     foreach ($importDataNamespace->data as $subscriberNum => $subscriber) 
     { 
      foreach ($fieldsMap as $fieldNumber => $fieldTag) { 
       if (isset($subscriber[$fieldNumber])) { 
        $subscriberData[$fieldTag] = $subscriber[$fieldNumber]; 
       } else { 
        $subscriberData[$fieldTag] = ''; 
       } 
      } 
      $query = 'INSERT INTO subscribers (list_id, account_id, email_address, first_name, last_name, date_added, last_changed) ' . 
        'VALUES (' . 52 . ', ' . 29 . ', \'' . $subscriberData['EMAIL'] . '\', \'' . $subscriberData['FNAME'] . 
        '\', \'' . $subscriberData['LNAME'] . '\', \'' . $dateAdded . '\', \'' . $lastChanged . '\')'; 
      $db->query($query);               
     } 
     $db->commit(); 

     $this->view->time = microtime(true) - $startTime; 

感谢您对这个问题的任何信息。

这段代码使用约0.065秒的mysql_query:

$dateAdded = date('Y-m-d H:i:s'); 
    $lastChanged = $dateAdded;  

    $startTime = microtime(true);  
    $result = mysql_query('BEGIN'); 
    for ($i = 0; $i < 100; $i++) { 
     $email = 'test_ ' . $i . '@gmail.com'; 
     $query = 'INSERT INTO subscribers (list_id, account_id, email_address, first_name, last_name, date_added, last_changed) ' . 
       'VALUES (' . 52 . ', ' . 29 . ', \'' . mysql_real_escape_string($email) . '\', \'' . mysql_real_escape_string($firstName) . 
       '\', \'' . mysql_real_escape_string($lastName) . '\', \'' . mysql_real_escape_string($dateAdded) . '\', \'' . mysql_real_escape_string($lastChanged) . '\')';                 
     mysql_query($query);    
    }    
    $result = mysql_query('COMMIT'); 
    $time = microtime(true) - $startTime;       
    echo 'Using mysql_query: ' . $time . '<br />'; 
    exit(); 

代码Zend_Db_Adapter对象基准(我甚至没有使用引号在这种情况下):

$db = Zend_Db_Table::getDefaultAdapter(); 
    $db->getProfiler()->setEnabled(true); 
    $profiler = $db->getProfiler();   

    $startTime = microtime(true); 
    $db->beginTransaction();   
    for ($i = 0; $i < 100; $i++) 
    { 

     $email = 'test_' . $i . '@gmail.com'; 
     $query = 'INSERT INTO subscribers (list_id, account_id, email_address, first_name, last_name, date_added, last_changed) ' . 
      'VALUES (' . 52 . ', ' . 29 . ', \'' . $email . '\', \'' . $firstName . 
      '\', \'' . $lastName . '\', \'' . $dateAdded . '\', \'' . $lastChanged . '\')'; 
     $db->query($query);         
    }   
    $db->commit(); 
    $time = microtime(true) - $startTime;      
    echo 'Time of transaction Zend_Db_Adapter query: ' . $time . '<br />'; 

    echo 'Total time ' . $profiler->getTotalElapsedSecs() . '<br />';   
    $count = 0; 
    $totalTime = 0; 
    foreach ($profiler->getQueryProfiles() as $query) { 
     $count++; 
     $elapsedTime = $query->getElapsedSecs(); 
     $totalTime += $elapsedTime; 
     echo $count . ' ' . $elapsedTime . ' ' . $query->getQuery() . '<br />'; 
    } 
    echo 'Sum time: ' . $totalTime . '<br />'; 

这里有一些结果:

交易查询Zend_Db_Adapter会时间:0.23094701767 总时间0.0949234962463 1 0.00199699401855连接 2 0.000336885452271开始 3 0.000540018081665 INSERT INTO订户(list_id,account_id,email_address,first_name,last_name,date_added,last_changed)VALUES(52,29,'[email protected]','John','Clinton','2011- 01-28 15:25:21','2011-01-28 15:25:21') 4 0.000504016876221 INSERT INTO订户(list_id,account_id,email_address,first_name,last_name,date_added,last_changed)VALUES(52,29, '[email protected]','John','Clinton','2011-01-28 15:25:21','2011-01-28 15:25:21')

这很奇怪。插入100条记录的交易时间是执行所有查询的2.5倍。 如果我试图在循环中形成字符串的时间(如果我们删除查询)并没有花费太多时间。

+0

如果你有一个有大量数据的大系统,你可能会认为doctrine2是一个ORM – Tjorriemorrie 2011-01-28 08:07:02

+0

是的,它会有相当多的数据。但Zend_Db_Adapter的问题仍然不清楚,是什么原因需要这么长时间。 – Oleg 2011-01-28 12:20:09

回答

0

mysql_ *函数是PHP的本地代码,所以它们非常快。

Zend_Db_Adapter正在使用PDO,因此您有第一个使用PDO的抽象层,第二个使用Zend_DB_Adapter。

你有更多的图层抽象,代码越来越慢。

那为什么MVC框架一般比程序代码更慢。

再次尝试用事先准备好的声明,并缓存机制您的标杆,你应该是接近的mysql_ *函数

+0

是的,我预计它会慢一点,但慢几倍,似乎太多了。 I – Oleg 2011-01-27 10:05:36

+1

它肯定强调了良好的服务器端缓存策略的好处,以尽可能避免成本高昂的数据库连接和查询。 – 2011-01-27 12:34:07

3

我认为,一个原因是,你执行的$ DB->报价()的次数太多,这是不必要的。你知道$ db-> quote()可以接受一个数组作为它的参数,并且你基本上可以将对$ db-> quote()的调用减少到只有一个。另外,在你的mysql_query版本中,你不会逃避$ dateAdded和$ lastChanged,而在zend_db版本中你不会。

编辑:添加下面

$db = Zend_Db_Table::getDefaultAdapter(); 

    $input = array(
     'a' => "asd'lfksd", 
     'b' => "asdlfk'sdfasdf", 
     'c' => "asd fds f saf'sdfsd", 
     'd' => "asd fds f saf'sdfsd" 
    ); 


    // separate calls to quote 
    $startTime = microtime(true); 
    $db->quote($input['a']); 
    $db->quote($input['b']); 
    $db->quote($input['c']); 
    $db->quote($input['d']); 
    $totalTime1 = microtime(true) - $startTime; 



    // one call to quote 
    $startTime = microtime(true); 
    $db->quote($input); 
    $totalTime2 = microtime(true) - $startTime; 

    // show results 
    var_dump("Sperate calls are ". $totalTime1/$totalTime2 . " times slower"); 
    //output: string 'Sperate calls are 3.0875831485588 times slower' (length=46) 
0

一个例子这看起来像你没有在Zend_Db的一个元数据缓存。

相关问题