如何在不破坏MySQL数据库的情况下跟踪综合浏览量

时间:2012-11-29 15:04:18

标签: php mysql

我正在尝试使用以下查询跟踪MySQL数据库中的网页浏览:

"UPDATE $table SET pageviews = pageviews + 1 WHERE page_id = 1"

这适用于低到中等流量。但是,在高流量时,对DB的不断写入会导致高读/写争用,最终导致数据库崩溃。

我已经在Stackoverflow和其他地方阅读了几个QA,其中建议使用MongoDB作为替代方案。但是,这个选择不可用,我必须坚持使用MySQL。此外,我无法控制引擎 - MyISAM或InnoDB(由于基于行的锁定而不是表格,InnoDB的性能更好,如MyISAM的情况)。

考虑到上述情况,在不破坏数据库(在数据库或其他情况下)的情况下,跟踪网页浏览的最佳方法是什么?我真的很感激答案提供代码片段作为起点(如果可行)。

BTW,我正在使用PHP。

更新: @fire在这里有一个很好的解决方案。但是,它需要使用memcache。我正在寻找一些可以轻松实现而无需特定基础知识的东西。这适用于几乎可以在不同托管环境中使用的模块。在第二个想法,我想到的是某种基于cookie或文件日志的实现。我不确定这种实施如何在实践中发挥作用。任何进一步的投入都非常受欢迎。

4 个答案:

答案 0 :(得分:15)

我会使用memcached存储计数,然后将它与cron上的数据库同步...

// Increment
$page_id = 1;
$memcache = new Memcache();
$memcache->connect('localhost', 11211);

if (!$memcache->get('page_' . $page_id)) {
    $memcache->set('page_' . $page_id, 1);
}
else {
    $memcache->increment('page_' . $page_id, 1);
}

// Cron
if ($pageviews = $memcache->get('page_' . $page_id)) {
    $sql = "UPDATE pages SET pageviews = pageviews + " . $pageviews . " WHERE page_id = " . $page_id;
    mysql_query($sql);
    $memcache->delete('page_' . $page_id);
}

答案 1 :(得分:1)

我会考虑使用您提供的最快的写入引擎收集原始点击数:

INSERT INTO hits (page_id, hit_date) VALUES (:page_id, CURRENT_TIMESTAMP)

...然后运行一个定期进程,可能是一个cron命令行脚本,它将按小时或每天计算并存储您需要的页数摘要:

INSERT INTO daily_stats (page_id, num_hits, day)
SELECT page_id, SUM(hit_id)
FROM hits
WHERE hit_date='2012-11-29'
GROUP BY page_id

(查询仅仅是示例,可根据您的需求进行调整)

另一个典型的解决方案是良好的旧日志解析,将AWStats等脚本与Web服务器的日志一起提供。

澄清:我的第一个建议与@fire's非常相似,但我没有进入存储详细信息。关键是要以最快的方式延迟繁重的处理和最小量的原始信息。

答案 2 :(得分:0)

您是否考虑过使用Google Analytics?

http://analytics.google.com

答案 3 :(得分:0)

您尚未指定此表的读取或写入速率。如果将索引保持在绝对最小值并且行大小很小,MySQL通常可以保持良好状态。具有页面ID和计数器列的表在大多数情况下应该非常快。

InnoDB也应该没问题。如果系统在重写活动期间崩溃或断电,MyISAM可能以最坏的方式爆炸,它不是记录的,也不能总是被恢复。 InnoDB更强大。

要从InnoDB获得最大性能,您需要根据standard guidelines调整服务器并积极地对其进行基准测试,以确保您做对了。每个操作系统都有它的怪癖。有时候,由于没有正确的设置,你可能会错过两倍的性能提升。

如果您的跟踪数据库很小,您可能希望创建一个由RAM磁盘支持的实例,并将其复制到另一台具有常规HD的服务器。由于您期望极高的写入活动,如果您可以在最糟糕的情况下(如系统崩溃)承受少量数据丢失,您可以定期mysqldump此数据库对其进行快照。将内存支持的数据库转储甚至一百万行应该只需要一分钟,并且不会因MVCC而中断写入。