怎么处理类似会员基数很大但活跃度很低的数据库设计问题?

李恒坤 发布于 2012/07/29 01:55
阅读 758
收藏 0

问大家一个很实际的问题:

有这样一个需求,会员之间可以相互发送消息,管理员可以管理消息,会员的数目达到100万,但活跃用户只有3万不到。

请问,对这种数据基数大,但是活跃度低的应用场景,一般是怎么去设计数据库结构和处理相互间数据的转换问题的?谢谢各位了!

 

(我自己设想的是,将会员表分为两个,一个活跃表,一个存档表,每次用户登录时先搜索活跃表,如果不存在则继续搜索存档表,用户登录成功后将其在存档表中的记录转移到活跃表中。但问题是,活跃表中的用户如果长期不登陆,通过什么策略将其数据转移到存档表呢?用定时器每天定时处理?)

加载中
0
Lunar_Lin
Lunar_Lin
不是很明白.你现在要解决什么问题? 读取DB速度? 
       内存够的话 将活跃用户的数据放在cache里按LRU 时间逐出.  如果说不存在活跃用户, 每个月随机活跃3w用户的话......这个不可能吧.呵呵.
李恒坤
李恒坤
解决读取DB速度的问题,我新手,您的解决方法还能更具体些么?比如怎么设计这个会员表?
0
mallon
mallon
这个没必要吧,按用户名建索引,100万的检索又算得了什么呢
李恒坤
李恒坤
实际中是存在这样的应用场景的,比如1000万条记录,平常经常用到的也就1万条左右,为了加快读取速度,是否可以采用某种策略,将这两种情况的数据分类处理?
0
Lunar_Lin
Lunar_Lin
1. 如果是DB机器负载压力大,  可以2/多台机器做读写分离, 代码上注意读写延迟即可.
2. 如果就是单纯的速度不够, 内存速度可以比DB快至少2个数量级.  a. 不知道你建了索引没有? 这个肯定要建. b. 审查下你的sql语句,不要使用复杂的逻辑,逻辑可以自己用程序去做. c. 把数据放在内存中.   比如你原先页面是直接读db,现在页面是调用一个服务程序,这个服务程序在自己内存数组存好用户的数据(c++的话用std:map就足够好了, C的话,找些开源实现吧,hash/红黑树 ), 内存中没查到的话,再去db取, 取到添加到内存中. 在这个内存结构过大的时候, 进行LRU的删除. (LRU的设计 我看stackoverflow上提到的也是 map+list, 这个应该是目前的最佳实现了.)
3. 数据库表设计这头,我看一般的说法,有索引的时候, 只要表项没超过百w级速度都是一样的吧.我不熟悉db这头的优化, 你可以专门找些资料看看. 暂时分表应该是没太大意义的. 当然设计上还是要留足,按时间段分/按用户名id段(or余数)分/按功能类型分/  的余地,以备未来的数据膨胀.

李恒坤
李恒坤
回复 @Lunar_Lin : 呵呵,是啊,我也感觉如果只在数据库层面解决这类大数据的活跃和非活跃问题确实会带来很多负面效应。您第一次说的解决方案蛮好的,把数据放在内存中,您是指的用memcache和redis之类的缓存系统吧?还有LRU算法,看起来很有用,只是生产环境中不知道如何去应用?
Lunar_Lin
Lunar_Lin
回复 @李恒坤 : 而且针对活跃/非活跃的切换, 你要在DB里移动数据的话, 发生大量用户抖动(一会活跃,一会不活跃,很快又活跃了)会耗性能的. 像我QQ空间曾经频繁使用,现在完全不用了.人人冷了一年,现在又用用, 微博频繁登录了3个月,现在又计划完全不上了. 哈哈哈.
Lunar_Lin
Lunar_Lin
回复 @李恒坤 : 不做DB,再细就不敢瞎说了. 这个数量级,个人感觉可以缓缓, 不用做分表, 如果DB query速度慢, 要找其他的原因. 不活跃用户和活跃用户是随时都会互相变化的, 在DB这种比较固定死的环节上固化.感觉不是很合适....纯个人意见.
李恒坤
李恒坤
非常感谢您详细的回答,您说的这几点对减轻DB负载和加快DB的读取速度都非常有效果。但我的重点偏向于数据库的表结构设计这块,针对数据基数大但活跃数据很低的情况,有没有专门针对这块的设计优化呢?
0
LeungBin
LeungBin
100w数据和1000w数据优化一下就得了,其实这个量很小。
0
LeungBin
LeungBin

如果真有需要可以考虑做缓存,给缓存设个有效期,如用memcached

用户第一次登陆从 memcached 读取读取,如果没有则从DB读取,然后放入memcached。

假设你给这个有效期设置为一个星期,那么这些活跃用户基本上在一个星期内都只读DB一次。

当然memcached也有命中率,但是已经很大程度上减轻db压力。

0
LeungBin
LeungBin

关于数据表结构设计,个人觉得不用做分表,千W级的表DB还可以挡得住,做好索引优化。

我曾经的项目有个单表6000多W还做多表查询效率都很高(Oracle的)

会员发送信息这个量有多大呢?

如果比较大可以考虑分表设计,按照月度来分表或者年度。

其实非关系型数据库很适合你的应用场景,可以考虑。

 

 

LeungBin
LeungBin
回复 @李恒坤 : mysql 我试过600w的数据 效率没问题
李恒坤
李恒坤
这种情况mysql跑起来不知道怎样,你说的方案很常用,谢谢了
0
杰克肖
杰克肖
用户信息表并非大量产生和操作的,因此不适合分表,建议在表的设计上增加一个是否活跃的布尔型字段,用于优化查询,这样足以优化性能,同时也可以作为初始缓冲的依据。至于是否活跃的判断,可以采用独立的一个算法,定期执行,比如一周执行一次,或者每天执行一次,也足够了。
0
Lunar_Lin
Lunar_Lin

LRU就是服务程序定义的map+list结构.我见有人用map套map来实现,个人感觉远没map+list好.你可以搜索下服务端 LRU cache; 很常见的做法. memcache在服务器上实在装不下足够比例的活跃用户数据时候再用, 因为它是基于网络的, 还多了网络IO的消耗. LRU cache把相当比例的 数据库读变成map读, 数据库写变成(map写+一个异步task写DB), 页面处理速度就会好很多,DB压力也下来了, 就是特耗内存.    加台机器跑memcache/redis是未来最后的正道, 那时候LRU内存可以拿来存一些索引,memcache用来存具体的数据内容. 消除大部分的DB读请求, LRU的目的就达到了.

返回顶部
顶部