2009-02-08 82 views
5

我想开始计算浏览网页的次数,因此需要某种简单的计数器。什么是最好的可扩展的方法呢?什么是在MySQL中实现计数器字段的最佳方式

假设我有,每一行对应一个页表Frobs - 一些明显的选项是:

  1. 在Frobs表,得到 使用UPDATE Frobs SET NumViews = NumViews + 1每个视图时更新有一个unsigned int NumViews场 。简单但不是很好,因为我了解它。

  2. 有一个单独的表FrobViews 其中为每个视图插入一个新行。要显示 的视图数量,则需要执行一个简单的SELECT COUNT(*) AS NumViews FROM FrobViews WHERE FrobId = '%d' GROUP BY FrobId。这不涉及任何更新,因此可以避免MyISAM表中的表锁定 - 但是,如果要显示每个页面上的视图数,读取性能将受到影响。

你是如何做到的?

这里有一些很好的建议: http://www.mysqlperformanceblog.com/2007/07/01/implementing-efficient-counters-with-mysql/ 但我希望听到SO社区的意见。

我目前使用InnoDb,但对InnoDb和MyISAM的答案感兴趣。

回答

2

我会采取第二种方法,并将数据从常规基础上的第一个解决方案汇总到表中。这样你就可以获得两种解决方案的优点。更清晰: 在每次击中时,您都会在表中插入一行(让它命名为hit_counters)。这张表只有一个字段(pageid)。每运行一个脚本(通过cronjob),它会聚合hit_counters表中的数据,并将其放到第二个表中(让它命名为'hit'),其中有两个字段:pageid和总点击数

林不知道,但恕我直言,没有InnoDB的不是帮助你非常多的解决方案1,如果你在同一页上的许多命中:Innodb的锁定该行同时更新,因此所有其他更新此行将会推迟

根据。什么是你写的程序也可以通过计算你的应用程序和更新数据库来每隔x秒更新一次,这只有在你使用持久存储的程序设计语言(比如Java Servlets而不是PHP)时才有效

3

如果可扩展性对您而言比数据的绝对准确性更重要,那么您可以在短时间内缓存应用程序中的查看计数,而不是在每个页面视图上都访问数据库 - 例如,每100次查看只更新一次数据库。

如果您的应用程序在数据库更新之间崩溃,那么显然您会丢失一些数据,但是如果您可以容忍一定数量的不准确性,那么这可能是一种有用的方法。

0

我做了什么,它可能不适用于您的场景,是在存储过程中准备/返回页面上显示的数据,我在使表格计数器更新的同时返回数据 - 这样,只有一个调用服务器的服务器都能获取数据,并在同一个调用中更新计数器。

如果您不使用SP的话(或者如果页面上没有数据库数据),您可能无法使用此选项,但如果您有此选项,则需要考虑。

3

插入到数据库中并不是您想在页面浏览中执行的操作。由于MySQL上的复制是单线程的,因此使用所有插入更新从属数据库可能会遇到问题。

在我的公司,我们每天服务25M页面,我们采取了分层的方法。

视图计数器存储在一个带有2列(profileId,viewCounter)的单独表中,它们都是无符号整数。

对于不经常查看的项目,我们更新页面视图上的表格。 对于经常查看的项目,我们会在1/10左右更新MySQL。对于这两种类型,我们都会在每次点击时更新Memcache。
int Memcache::increment (string $key [, int $value = 1 ])

if (pageViews < 10000) { UPDATE page_view SET viewCounter=viewCounter+1 WHERE profileId = :? }

else if ((int)rand(10) == 1) { //UPDATE page_view SET viewCounter= ?:cache_value WHERE profileId = :? }

做COUNT(*)是InnoDB的效率非常低(的MyISAM保持计数在索引统计信息),但是一个MyISAM将锁表上读降低并发性。对50,000或100,000行进行count()将花费很长时间。在PK上做选择会非常快。

如果你需要更多的扩展性,你可能想看看redis

相关问题