如何在不影响性能的情况下计算MySQL中的页面浏览量

如何在不影响性能的情况下计算MySQL中的页面浏览量,mysql,performance,Mysql,Performance,我想计算一个页面的访问者数量,类似于stackoverflow对每个问题的“视图”所做的操作 当前解决方案只是增加InnoDB表的一个字段: UPDATE data SET readers = readers + 1, date_edited = date_edited WHERE ID = '881529' LIMIT 1 UPDATE data d, mem_table m SET d.readers = d.readers + m.readers_new WHERE d.ID

我想计算一个页面的访问者数量,类似于stackoverflow对每个问题的“视图”所做的操作

当前解决方案只是增加InnoDB表的一个字段:

UPDATE data SET readers = readers + 1, date_edited = date_edited    WHERE ID = '881529' LIMIT 1
UPDATE data d, mem_table m
SET d.readers = d.readers + m.readers_new   
WHERE d.ID = m.ID;

DELETE FROM mem_table;
这是页面上最昂贵的查询,因为它正在执行写入操作

有更好的办法解决这个问题吗?像stackoverflow这样的高流量站点如何处理这个问题

我想改为使用内存引擎写入一个表,每隔一分钟左右将内容写入innodb表

e、 g:

然后我会每分钟运行一个cron作业来更新InnoDB表:

UPDATE data SET readers = readers + 1, date_edited = date_edited    WHERE ID = '881529' LIMIT 1
UPDATE data d, mem_table m
SET d.readers = d.readers + m.readers_new   
WHERE d.ID = m.ID;

DELETE FROM mem_table;
不幸的是,这在复制方面不是很好,应用程序使用的是MySQL Galera集群


提前感谢您的建议。

有一些方法可以通过启动单独的线程来更新计数器来降低即时性能的影响。当您有大量并行用户(命中计数器的并行更新如此之多)时,建议使用排队机制来防止锁定(就像内存中的表一样)。队列将同时具有写入和读取,因此必须考虑表和数据设计


另一种方法是将与文章相关的计数器保存在单独的文件中。这可以防止具有命中计数器的单个表上出现拥塞,或者如果您将其保留在提供项目的表中,则会导致该项目表上出现高锁等待超时(导致所有类型的前端错误)。将数据保存在单独的文件中并不能让您了解站点的整体点击率,但为此,您可以使用awstats之类的日志绘图工具。

有一些方法可以通过启动单独的线程来更新计数器来降低即时性能影响。当您有大量并行用户(命中计数器的并行更新如此之多)时,建议使用排队机制来防止锁定(就像内存中的表一样)。队列将同时具有写入和读取,因此必须考虑表和数据设计


另一种方法是将与文章相关的计数器保存在单独的文件中。这可以防止具有命中计数器的单个表上出现拥塞,或者如果您将其保留在提供项目的表中,则会导致该项目表上出现高锁等待超时(导致所有类型的前端错误)。将数据保存在单独的文件中并不能让您了解网站的整体点击率,但为此,您可以使用awstats之类的日志绘图工具。

如果您可以在一条语句中同时批处理100次
插入
/
更新
,则可以将其运行速度提高10倍。(存在
锁定\u等待\u超时
和/或死锁的风险。)

如果您构建一个
内存
表,并在断电时丢失排队的数据,该怎么办?我想这个应用程序可以吗?(如果不是,你就有一个更大的问题。)

你的客户是什么?他们能在接触数据库之前排队吗

我喜欢乒乓一对表,以便将数据转移到数据库中。客户端向一个表写入数据;一个连续运行的作业(不是cron作业)正在使用另一个表。当后者完成插入/更新时,它将使用单个原子的
重命名表来交换表,这样客户机就不被注意了。对此进行了更详细的讨论。它解释了如何避免您遇到的复制问题

另一个提示。不要将计数和日期放在主表中。将它们放在“并行表”(“垂直分区”)中。这减少了复制中的体积,并减少了对其他处理的干扰

对于Galera,使用一对非复制表(建议使用不带索引的MyISAM)。让连续运行的作业在一个位置运行,在3个节点之间循环。如果你有3份工作,他们可能会在很多方面互相绊倒


如果这不能持续下去,你需要切分你的数据。(大人物迟早都会这么做。)

如果你能在一条语句中同时批处理100个
插入
/
更新
,那么你可以以10倍的速度运行它。(存在
锁定\u等待\u超时
和/或死锁的风险。)

如果您构建一个
内存
表,并在断电时丢失排队的数据,该怎么办?我想这个应用程序可以吗?(如果不是,你就有一个更大的问题。)

你的客户是什么?他们能在接触数据库之前排队吗

我喜欢乒乓一对表,以便将数据转移到数据库中。客户端向一个表写入数据;一个连续运行的作业(不是cron作业)正在使用另一个表。当后者完成插入/更新时,它将使用单个原子的
重命名表来交换表,这样客户机就不被注意了。对此进行了更详细的讨论。它解释了如何避免您遇到的复制问题

另一个提示。不要将计数和日期放在主表中。将它们放在“并行表”(“垂直分区”)中。这减少了复制中的体积,并减少了对其他处理的干扰

对于Galera,使用一对非复制表(建议使用不带索引的MyISAM)。让连续运行的作业在一个位置运行,在3个节点之间循环。如果你有3份工作,他们可能会在很多方面互相绊倒


如果这不能持续下去,你需要切分你的数据。(大人物迟早都会这么做。)

谢谢你的帮助。不过我不确定我是否正确理解了你的建议。您是否建议将信息存储在文件系统的文件中?这不是一个严重的性能影响吗?附加到文件不是一个“严重的”性能影响。文件在写入之前也是由操作系统缓存的,因此文件解决方案是一个非防崩溃的解决方案:某些写入可能会