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

使用数据库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

学习是最好的投资!

reply all(4)
巴扎黑

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

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

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

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

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

Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!