Mysql計數器表設計

2021-08-01 16:28:45 字數 1789 閱讀 4107

mysql> create table hit_counter(

-> cnt int unsigned not null

-> ) engine=innodb;

mysql> update hit_counter set cnt=cnt+1;
問題在於,對於任何想要更新這一行的事務來說,這條記錄上都有乙個全域性的互斥鎖(mutex)。這會使得這些事務只能序列執行。要想獲得更高的併發更新效能,也可以將計數器儲存在多行中,每次隨機選擇一行進行更新。這樣做需要對計數器表進行如下修改:

mysql> create table hit_counter(

-> slot tinyint unsigned not null primary key,

-> cnt int unsigned not null

-> ) engine=innodb;

然後預先在這張表增加100行資料。現在選擇乙個隨機的槽(slot)進行更新:

mysql> update hit_counter set cnt=cnt+1

where slot=rand()*100;

要獲得統計結果,需要使用下面的聚合查詢:

select

sum(cnt) from hit_counter;

乙個常見的需求使每隔一段時間開始乙個新的計數器(例如每天乙個)。如果需要這麼做,則可以再簡單的修改一下表設計:

mysql> create table daily_hit_counter(-> day date not

null,-> slot tinyint unsgined not

null,-> cnt int unsigned not

null,-> primary key(day,slot)

-> ) engine=innodb;

在這個場景中,可以不用像前面的例子那樣預先生成行,而用on duplicate key update代替:

mysql> insert into daily_hit_counter(day, slot, cnt)

-> values(current_date, rand()*100,1)

->

on duplicate key update cnt=cnt+1

如果希望減少表的行數,以避免表變得太大,可以寫乙個週期執行的任務,合併所有結果到0號槽,並且刪除所有其他的槽:

mysql> update daily_hit_counter as c

-> inner join (

->

select day, sum(cnt) as cnt min(slot) as mslot

-> from daily_hit_counter

->

group

by day

-> ) as x using(day)

->

set c.cnt=

if(c.slot=x.mslot, x.cnt, 0),

-> c.slot=

if(c.slot=x.mslot,0 ,c.slot);

mysql> delete from daily_hit_counter where slot<>

0and cnt=

0;

MySQL 計數器表

計數器表的建立 create table hit counter cnt int unsigned not null engine innodb update hit counter set cnt cnt 1 問題在於,對於任何想要更新這一行的事務來說,這條記錄上都有乙個全域性的互斥鎖 mutex...

計數器設計

最近看到一篇文章說要實現乙個計數器的功能,於是通過思索,設計了乙個靈活可用性高的物件計數器。裡面閃爍著 很多的火花。template class object counter object counter private static int m count template int object ...

mysql計數 mysql實現計數器

本文 如果是在非常高的併發之下,還是建議用記憶體資料庫redis去實現計數的功能。如果不是那麼高的併發,用表實現就可以。drop table access counter create table access counter cnt int unsigned not null insert int...