科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道Schema的优化和索引 - 范式和非范式7

Schema的优化和索引 - 范式和非范式7

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

Schema的优化和索引 - 范式和非范式

作者:ddvip 来源:ddvip 2009年12月22日

关键字: Schema PHP MySQL

  • 评论
  • 分享微博
  • 分享邮件

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领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章