扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
Schema的优化和索引 - 范式和非范式7
每次点击都更新计数列。
mysql> UPDATE hit_counter SET cnt = cnt + 1;
这样做问题在于这个单独的行是对于任意更新计数的事物是全局互斥的。它会序列化这些事物。为了获得更高的并发,可以保存更多的行并且随机更新这些行。表的修改如下
mysql> CREATE TABLE hit_counter (
-> slot tinyint unsigned not null primary key,
-> cnt int unsigned not null
-> ) ENGINE=InnoDB;
预先给这个表添加100行,现在这个查询就随机更新计数了。
mysql> UPDATE hit_counter SET cnt = cnt + 1 WHERE slot = RAND( ) * 100;
为了获取统计信息,可以使用聚合查询
mysql> SELECT SUM(cnt) FROM hit_counter;
还有一个一般需求就是需要每个周期的计数。(比如,一天一次)。如果你需要这么做,你可以修改下数据模型。
mysql> CREATE TABLE daily_hit_counter (
-> day date not null,
-> slot tinyint unsigned 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;
如果你想减少一些行来使表变得更小,你可以写一个周期性的任务来把合并所有的结果到slot()并且上除其他的slot.
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 <> 0 AND cnt = 0;
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者