在我的网站上,我编写了一个函数,向您显示每天有多less访问者和多less个综合浏览量。
问题是,有时插入查询需要永远在InnoDB中没有DELAYED INSERT
函数。
编辑:这是使用InnoDB,我的意思是与长时间加载时间约6秒,而不是像0.1-0.5秒。 只要我删除日志logging的网站是快得多。
下面的$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);
和插入function码:
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(); }
一个小的优化。 你正在做绑定的方式,你可以摆脱foreach语句,并直接传递数组来执行。 PDO会将数组键映射到您在prepare语句中创建的:binding名称。
$sth->execute($data);
这就是说,你应该看看你在mysql中的慢查询日志,看看发生了什么。 即使您使用的是Innodb,Innodb也会锁定表格。 这可能是为什么插入有时需要很长时间。 您可以将您的缓慢查询阈值减少到3秒钟以捕获查询。 日志会告诉你在每个阶段花了多少时间(即锁定)。
“在我的网站上,我编写了一个功能,可以显示每天有多少访问者和多少个综合浏览量。”
你是否对每个页面请求执行实时查询? 这可能是一个性能问题。 如果你每隔一个小时左右查询这些数字,就不会杀死任何人,并缓存价值。 随后的页面视图可以使用缓存的值而不是活动的值。
“问题是,有时插入查询需要永远,InnoDB中没有DELAYED INSERT函数。”
这可能是因为它不是INSERT本身会让你放慢速度,但是你的MySQL实例只是在忙于计算页面浏览量。 一旦开始提供缓存页面视图数据,这个问题就有可能消失。
正如deceze所说,可能需要更多的细节。 但我想它可能会卡在“Config :: getValue('site','url')”。 顺便说一句,你的mysql是一个远程的?
是否有一个原因,你正在使用prepare
而不是只调用pdo -> exec()
?
搜索显示,许多人对基准测试prepare
,因为比使用exec()
更慢,更密集,尤其是当你不希望返回任何值时(另请参阅文档Prepare – 它被设计为优化调用相同的查询次)。
而不是绑定你的价值观,你可以做这样的事情 –
function insert($table, $data) { ksort($data); $fieldNames = implode("`, `", array_keys($data)); $fieldValues = implode("', '", array_values($data)); $this->exec("INSERT INTO $table (`{$fieldNames}`) VALUES ('{$fieldValues}')"); }