在我的网站上,我编写了一个功能,可以显示每天访问的访问者数量和浏览量。
问题是有时插入查询需要永远,而InnoDB中没有DELAYED INSERT
函数。
编辑: 正在使用InnoDB,我的意思是加载时间长约6秒而不是0.1-0.5秒。一旦我删除了日志记录,网站就会快得多。
下面的$b
数组包含浏览器信息,但根据XHProf,它的PDO查询需要很长时间才能执行。
插入代码是:
$values = array(
'time' => time(),
'ip' => $_SERVER['REMOTE_ADDR'],
'page' => rtrim((isset($_GET['q']) ? $_GET['q'] : 'index'), '/'),
'browser' => $b[11][0] . ' ' . $b[11][1],
'os' => $uos,
'referred' => (isset($_SERVER['HTTP_REFERER']) && !preg_match('|^' . Config::getValue('site', 'url') . '|', $_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ''),
);
$this->table->insert($values);
和插入功能代码:
public function insert($table, $data) {
ksort($data);
$fieldNames = implode('`, `', array_keys($data));
$fieldValues = ':' . implode(', :', array_keys($data));
$sth = $this->prepare('INSERT INTO ' . $table . '(`' . $fieldNames . '`) VALUES (' . $fieldValues . ');');
foreach ($data as $key => $value) {
$sth->bindValue(':' . $key, $value);
}
$sth->execute();
}
答案 0 :(得分:1)
“在我的网站上,我编写了一个功能,可以显示每天访问的访问者数量和浏览量。”
您是否正在为每个页面请求执行实时查询?这可能是它自己的性能问题。如果您每小时左右查询这些数字,并且缓存该值,它不会杀死任何人。然后,后续页面视图可以使用缓存值而不是实时值。
“问题是有时插入查询需要永远,而InnoDB中没有DELAYED INSERT函数。”
可能是它不是INSERT本身会降低你的速度,但是你的MySQL实例总是忙于计算页面浏览量。一旦开始提供缓存的页面视图数据,这个问题就有可能消失。
答案 1 :(得分:1)
次要优化。你进行绑定的方式可以摆脱foreach语句并直接传递数组来执行。 PDO会将数组键映射到您在prepare语句中创建的绑定名称。
$sth->execute($data);
那就是说,你应该看看mysql中的慢查询日志,看看发生了什么。即使您使用的是Innodb,也有一些场景会让Innodb锁定桌子。这可能就是为什么插件有时需要很长时间。您可以将慢查询阈值减少到3秒以捕获查询。日志将告诉您每个阶段花费了多少时间(即锁定)。
答案 2 :(得分:0)
正如deceze所说,它可能需要更多细节。但我想它可能会陷入“Config :: getValue('site','url')”。顺便说一句,你的mysql是远程的吗?
答案 3 :(得分:-3)
您是否有理由使用prepare
而不是仅仅致电pdo -> exec()
?
搜索周围显示许多人将基准标记prepare
标记为比使用exec()
慢得多且密集程度更高,尤其是当您不期待任何值时(另请参阅{{3}的文档) - 它注意到被设计为优化多次调用相同的查询。)
不是绑定你的值,你可以做这样的事情 -
function insert($table, $data) {
ksort($data);
$fieldNames = implode("`, `", array_keys($data));
$fieldValues = implode("', '", array_values($data));
$this->exec("INSERT INTO $table (`{$fieldNames}`) VALUES ('{$fieldValues}')");
}