MySQL包含需要“随时间变化值”的排序字段的数据库设计
PHPz
PHPz 2017-04-17 11:16:23
0
4
618

使用数据库MySQL(innodb)
相关表设计最大数据量:5000w

假定表news,拥有以下字段:

id int auto_increment,
title varchar(2000) not null default '' comment '标题',
score int not null default 0 comment '基础分值',
visited int not null default 0 comment '展示次数',
voted int not null default 0 comment '投票数',
//hot int not null default 0 comment '热度', 不再作为独立字段,而是在select的时候来计算
created int not null default 0 comment '创建Unix时间戳',
primary key(id),
key score(score),
key visted(visited),
key voted(voted),
key created(created)

其中,hot字段的值是结合visited、voted计算并随着时间衰减的,衰减频率最短为1小时(即间隔1小时就需要根据当前时间戳与created的差值做一次衰减)。数据主要根据hot字段的值来排序展示的,因此需要保证整表hot数据的更新。

另外,我还需要记录一个hot的历史最高值。(补充)hot值有最大限制,不能超过100。

难点:如果独立一个hot字段,数据量大了之后,衰减更新的效率将非常之低并影响系统整体性能;如果另外设一个完全不包含衰减的分数值字段score,需要展示的时候实时再实时计算hot的值又怕SQL执行效率太低。

目前后者的效率肯定更高,不知道各位大神有没有做过类似的需求,有没有更好的方案,求解!


确定在visit和vote操作时更新递增的score值,然后在SELECT列表的时候实时计算经过时间衰减的hot值,对于提取的数据先通过where条件缩小范围,结果进行一定时间的cache缓存。感谢大家!

PHPz
PHPz

学习是最好的投资!

全部回复(4)
巴扎黑

这种设计有点让人迷惑,我在想为啥要设计衰减这个操作啊,如果时间因子是T的话,完全可以设计类似的公式啊

hot = f(visited) * f(voted) * T

越新的内容T肯定越大,所以即使他们的visitedvoted相同,它的hot值也会大些,如果你不希望时间因子的扰动有这么大的话也可以

hot = f(visited) * f(voted) + f(T)

这样hot值只需要一次计算就行了,不需要实时更新,因为你已经把时间因子设计到它里面了

刘奇

我会展示的时候再实时计算hot的值,这样不受一小时的粒度限制,排序可以更实时地变化。

如果效率太低,我就把最终考虑所有因素后生成的结果缓存起来。

另:有种暗暗的感觉,题主一定是深受《基于用户投票的排名算法》系列文章毒害颇深。

黄舟

很奇怪的做法,这个hot就不应该和原始数据放到一起,笨一点就用一个专用slave表每小时sql排序一次,彻底一点就单写一个模块去随时更新每个条目的hot值,存到另外一个地方供读取用。

大家讲道理

不好意思,想咨询一下,您这个排名方式最终的实现方式,本人最近也受到类似问题困扰,感谢您的指导。。。谢谢。。

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责声明 Sitemap
PHP中文网:公益在线PHP培训,帮助PHP学习者快速成长!