为什么 Zend_Db_Adapter 比 mysql_query 慢很多
我在我的项目中使用 Zend 框架。我需要插入多条记录,我发现 Zend_Db 比 my_sql 查询慢得多(好几次),这让我觉得我做错了什么。 这里有两个例子。
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 的任何引用,则从带有引用的 14 秒开始,它花费了 12 秒,但它仍然比使用 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;
感谢您提供有关此问题的任何信息。
此代码使用 mysql_query 大约需要 0.065 秒:
$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) 值 (52, 29, '[电子邮件受保护]', '约翰', '克林顿', '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) 值 (52, 29, '[电子邮件受保护]', '约翰', '克林顿', '2011-01-28 15:25:21', '2011-01-28 15:25:21' )
这很奇怪。插入100条记录的事务时间是执行所有查询的2.5倍。 如果我尝试计算在循环中形成字符串的时间(如果我们删除查询)则不会花费太多时间。
I use Zend Framework in my project. I need to insert multiple records and I found that Zend_Db suprisingly slower thatn my_sql query (several times), that made me think I did something wrong.
Here are two examples.
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;
Example with 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;
In the first case it took 14.8 seconds, in the second 3.7.
Could you tell me why does it happend and what do you do wrong?
If I delete any quote for Zend_Db it took 12 seconds from 14 with quote, but it's still much more slower than with 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;
Thank you for any information about this issue.
This code takes about 0.065 seconds with 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();
Code with benchmark of Zend_Db_Adapter (I didn't even use quote in this case):
$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 />';
Here are some results:
Time of transaction Zend_Db_Adapter query: 0.23094701767
Total time 0.0949234962463
1 0.00199699401855 connect
2 0.000336885452271 begin
3 0.000540018081665 INSERT INTO subscribers (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 subscribers (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')
It's very strange. The time of transacation to insert 100 records is 2.5 times more than executing of all queries.
If I try to meach the time of forming strings in the loop it (if we delete query) doesn't take so much time.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我认为原因之一是您执行 $db->quote() 的次数太多,这是不必要的。您是否知道 $db->quote() 可以将数组作为其参数,并且您基本上可以将对 $db->quote() 的调用减少到只有一个。此外,在 mysql_query 版本中,您不会转义 $dateAdded 和 $lastChanged,而在 zend_db 版本中,您会转义。
编辑:添加了下面的示例
I think that one reason is that you execute $db->quote() too many times, which is unnecessary. Do you know that $db->quote() can take an array as its argument and you can basically reduce calls to $db->quote() to only one. In addition in your mysql_query version you do not escape $dateAdded and $lastChanged, while in zend_db version you do.
EDIT: Added an example below
mysql_* 函数是 PHP 的原生函数,因此它们非常快。
Zend_Db_Adapter 与 PDO 一起使用,因此您有第一个带有 PDO 的抽象层,第二个带有 Zend_DB_Adapter 的抽象层。
层抽象越多,代码速度就越慢。
这就是为什么 MVC 框架通常比过程代码慢的原因。
再次尝试使用准备好的语句和缓存机制进行基准测试,您应该接近 mysql_* 函数
mysql_* functions are natives to PHP , so they are very fast.
Zend_Db_Adapter is working with PDO so you have a first absraction layer with PDO and a second with Zend_DB_Adapter.
More layer abstraction you 've got , more the code is slowing down.
That why the MVC framework in general are more slower than procedural code.
Try again your benchmark with prepared statement and a cache mechanism and you should be close of the mysql_* functions
这看起来像您在 Zend_Db 中没有元数据缓存。
This looks like you don't have a metadata cache in Zend_Db.