计数器表的简单使用

Posted zzliu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了计数器表的简单使用相关的知识,希望对你有一定的参考价值。

本文整理自《高性能mysql》第三版,修正了部分错误

计数器表

web应用中经常需要保存用户的朋友数,点击次数,文件下载次数等,如果在应用表里面保存计数器,那么在更新计数器时可能遇到并发文婷,因此创建要给独立的表存储计数器通常是个好主意,这样可以使计数器小且快,使用独立的表可以帮助避免查询缓存失效。

CREATE TABLE hit_counter (
    cnt int unsigned not null
) ENGINE=InnoDB;



网站的每次点击都会对计数器进行更新

UPDATE hit_counter set cnt = cnt + 1



问题在于,对于每一个想要更新这一行的事务来说,这条记录上都有一个全局互斥锁(mutex),这会使事务只能串行执行。要获得更高的并发更新性能,可以将计数器保存在多行中,每次随机选择一行更新。

CREATE TABLE hit_counter (
    slot tinyint unsigned not null,
    cnt int unsigned not null,
    PRIMARY KEY (slot)
) ENGINE=InnoDB;



然后预先在这张表里增加100行(根据业务需要确定)数据,更新时随机选择一行更新

UPDATE hit_counter set cnt = cnt + 1 where slot = ROUND(RAND() * 100);

注:mysql的RAND()函数返回0,1之间的随机浮点数



一个常见的需求是每隔一段时间开始一个新的计数器(例如,每天一个),可以通过修改表结构实现

CREATE TABLE daily_hit_counter (
    day date not null,
    slot tinyint unsigned not null,
    PRIMARY KEY (day,slot)
) ENGINE=InnoDB;



更新时只需要执行下面的语句

insert into daily_hit_counter values (CURRENT_DATE,ROUND(RAND()*100), 1)
ON DUPLICATE KEY UPDATE cnt = cnt + 1;



如果希望减少表的行数,可以写一个周期性的任务,合并所有结果到0号槽,并且删除所有其他的槽。实现起来也很简单,就不赘述了

以上是关于计数器表的简单使用的主要内容,如果未能解决你的问题,请参考以下文章

神经网络:神秘的ReLu

为啥保守光栅化无法为某些三角形调用片段着色器?

简单计数查询的成本

桶排序和计数排序

使用 Criteria API 根据条件计算加入表的结果

如何制作更新不同表的计数器触发器?