排行榜数据库设计与分析为什么实时排行不可行?

很多网游中都有排行榜,这里就专门讨论一下这个排行榜背后的数据库设计。一开始我觉得这是一个基本的数据库设计问题。只需要有一个实体,没有实体间的关系,没有复杂的逻辑。网络上也搜索不到太多关于这类设计的问题,好像根本不值得为其写个文章。但是在公司专门做了一个月的排行榜数据库设计。才发现问题根本没有看上去那么简单。甚至一篇文章都难以讲明白。不知自己误入歧途了,还是这个问题的确就是很复杂的。所以写个文章讲给大家,或许能有人一语道破。

一开始听到要设计一个排行榜,觉得很简单,一个外键加一个分数列,排名不保存在数据库中,每次查询都实时计算。不就得了?

接下来,就来讨论一下这种方案的可行性。先来描述一下经过最简化的基本要求:

1.       参与排行的设计用户量为1000万左右。

2.       并不要求实时,一小时更新一次。(我一开始的想法很天真,实时不是更好?所以才试了这个实时的排行榜)

3.       排行榜的结果要正确。(最废话的一条,其实很关键,直接导致实时方案作废)

生产环境,数据库服务器:

CPU:双路4核,至强。

内存:32G。

开发、测试的环境:(以下运行时间数据基于此环境)

CPU:赛扬D 2.66G

内存:1G。

建表:

Create Table RealTimeCLB

(

UserId INT NOT NULL PRIMARY KEY,

Rating INT NOT NULL

)

放数据:一定要用Tran。

BEGIN TRAN

DECLARE @I as int

SET @I = 0

INSERTDATA:

INSERT RealTimeCLB VALUES(@I, RAND()*10000000)

SET @I = @I + 1

IF @I < 5000000

GOTO INSERTDATA

COMMIT TRAN

插入500万数据就用了16分钟,心里有点怵了。实时计算排名会不会慢呢?不管了,试试再说,反正真正的服务器很强大的说。注意Rating值是用随机数生成的。

为Rating列加索引:

CREATE INDEX IX_RealTimeCLB_Rating ON RealTimeCLB (Rating);

加索引又用了30秒。

查询:

SELECT TOP 100 *, RANK() OVER (ORDER BY Rating DESC) AS [rank] FROM RealTimeCLB

用时0秒。很快啊。会不会影响并发的数据更新呢?

UPDATE RealTimeCLB SET Rating = Rating + RAND() * 1000 where UserId = 2

运行没有影响。

这里要解释一个问题。如果查询时,有更新操作,那查询出来的不就是脏的了吗?这个是可以接受了。更新晚于查询,再正常不过了。所以这个不是个问题。

但是如果世界就这么和谐了,也就不用研究一个月了。本文只是这一个月的第一天而已。

因为查询的方式多种多样。上面只查了前100名,很快。但是如果随便一个想查一下自己的名次呢?这也是必须要实现的基本功能。

查询指定用户的名次:

SELECT *, RANK() OVER (ORDER BY Rating DESC) AS [rank]

FROM RealTimeCLB WHERE UserId = 1

如果你看到这里没有大叫,就说明你没有仔细看,或者至少对SQL不熟悉。因为上面的语句永远返回1。无论查谁,都是第1。

正确的SQL有很多写法,下面是其中一种:

SELECT * from

(SELECT *, RANK() OVER (ORDER BY Rating DESC) AS [rank] FROM RealTimeCLB) AS d

WHERE d.UserId = 1

很不幸,这条语句用了4.5秒。如果用1000万用户的数据量,岂不是要10秒?如果你不知道为什么查询自己很慢,就找本书看看索引是如何运作的吧。这里我就不解释了。

也许我的SQL比较低效(你有快的吗?要实时计算。)。但是QQ和MSN之类用户已经有2亿了,如果那天也要做个迅雷样的排行榜。实时?那还了得?数据库服务器天天别干别的了,光排个名就排不过来了。

把Rank做为一列放进表里,查询不就快了?那更新不就慢了?更新一个人的分数,就要给一群人重新计算排名。你SQL写得好,在500万数据量上,也要5秒运行时间。

所以结论就是,排行榜,在大用户量和当前硬件环境下,是不可能实时的。

如果有人说,我们数据量很小,就10万用户,那总可以了吧?一次查询也就0.05秒,还可以了。听上去是可以了。SQL Server 2005提供的Rank函数,让按列计算排名快了很多。但是还是不行!因为上面的方法,无法保证最基本的一个需求,正确性!

可以不管查询出来的数据是旧的,但是一定要正确啊。但是上面的方案,不能保证查询结果的正确性!

而下面的解释,才是本文的重点部分。

回到查询语句

SELECT * from

(SELECT *, RANK() OVER (ORDER BY Rating DESC) AS [rank] FROM RealTimeCLB) AS d

WHERE d.UserId = 1

UserId是外键,而且用来查询的UserId一定存在,但是就是这个语句会出问题,有看出什么问题吗?

问题就在于,这个语句返回的行数不确定!逻辑上,一个User一个Rank,但是这个语句,可能会返回两个或两个以上的结果行,甚至可能没有返回(即使UserId存在)。

出现的必要条件:

1.       在这个查询语句正确运行时,同时有数据更新。

2.       表上的Rating列建有索引。

表上有索引,就可能有这个问题,经过测试,如果把表上的索引删除,这个语句一定有一个返回行。

大家应该已经猜到问题的所在。在有索引的表上更新索引列,索引树为了保持平衡,就要同时改变索引数据的位置。如果同时有基于此索引的查询,就有可能因为索引节点在索引树上跳来跳去而遗漏或是重复读取一些节点。从而导致上面的问题。

解决方案1:查询时加表锁。既保证了正确性,又保证了时效性。但是查询的时候,就不能更新数据了。放弃。

解决方案2:不加索引。先把索引删除。

DROP INDEX IX_RealTimeCLB_Rating ON RealTimeCLB

那么在500万数据量下的查询速度如何呢?

SELECT TOP 100 *, RANK() OVER (ORDER BY Rating DESC) AS [rank] FROM RealTimeCLB

要21秒。100万数据要4秒。基本上成正比。其实时间就是花在了排序上。所以运行时间基本上只和排序算法的效率相关。因为没有了索引,所以查询一个用户的时间也和这个差不多。如果你说你们只有几千用户量,还可以试下这个方法。

解决方案3:还是别实时了~~~~~,详见下回分解。

时间: 2024-08-03 02:03:25

排行榜数据库设计与分析为什么实时排行不可行?的相关文章

艾伟_转载:排行榜数据库设计与分析——为什么实时排行不可行?

很多网游中都有排行榜,这里就专门讨论一下这个排行榜背后的数据库设计.一开始我觉得这是一个基本的数据库设计问题.只需要有一个实体,没有实体间的关系,没有复杂的逻辑.网络上也搜索不到太多关于这类设计的问题,好像根本不值得为其写个文章.但是在公司专门做了一个月的排行榜数据库设计.才发现问题根本没有看上去那么简单.甚至一篇文章都难以讲明白.不知自己误入歧途了,还是这个问题的确就是很复杂的.所以写个文章讲给大家,或许能有人一语道破. 一开始听到要设计一个排行榜,觉得很简单,一个外键加一个分数列,排名不保存

分析论坛数据库设计&amp;amp;分析

1,数据库设计 论坛数据库设计还是挺有意思的,按照业务逻辑进行拆分的数据库设计. 首先,如果是一个博客就一个post表记可以了.然后考虑到论坛数据量比较大,所以在设计上有优化. 论坛把数据库分成3个数据表,这样在访问不同页面的时候都查询很快. 数据库表参考discuz 数据库设计: 只是挑了些相关字段,没有把所有字段列出了. --论坛板块表 CREATE TABLE forum ( fid mediumint(8) unsigned NOT NULL AUTO_INCREMENT, `name`

ORACLE 数据库设计看哪本书好

问题描述 我想向数据库设计.分析方面进军. 解决方案 Thomas Kyte写的几本书,都好好的读一读.<<ORACLE专家高级编程>><<Oracle9i &10g编程艺术 >><<oracle9i高效编程>>解决方案二:<<Expert One-on-one Oracle>>不错,不过看什么书都不如看oracle官方文档解决方案三:Oracle的OCA考试认真的SQL部分.解决方案四:<Ora

经营分析、决策系统数据库设计 - 实时圈选、透视、估算

标签 PostgreSQL , 经营分析系统 , 手机行业 , 标签 , 圈选 , 透视 , 估值 , 决策 背景 经营分析.决策支持是现代企业的一个让数据发挥有效价值的分析型系统. 在各个行业中随处可见,例如共享充电宝中,协助销售了解实时的设备租赁情况,销售业绩.在电商中,协助小二和商户发掘目标用户群体.金融行业中,协助输出国民的存款.消费.贷款的画像. PostgreSQL, Greenplum都是非常适合于经营分析.决策支持的数据库.因为它们具备了一些特性,适合实时的分析透视.(流式计算.

恭迎万亿级营销(圈人)潇洒的迈入毫秒时代 - 万亿user_tags级实时推荐系统数据库设计

标签 PostgreSQL , 标签 , 推荐系统 , 实时圈人 , 数组 , gin , gist , 索引 , rum , tsvector , tsquery , 万亿 , user , tag , 淘宝 背景 我们仅用了PostgreSQL的两个小特性,却解决了业务困扰已久的大问题. 推荐系统是广告营销平台的奶牛,其核心是精准.实时.高效. 这么多广告平台,到底谁家强?谁的核心牛逼? 1. 精准,指对用户的描述精准,通常需要基于大量的用户行为数据,经历深度学习后形成的用户画像,或称之为标

[收藏]数据库设计中的反规范技术探讨

规范|设计|数据|数据库|数据库设计   数据库设计中的反规范技术探讨   注:这是很久以前在一个论坛看到的文章,觉得写的不错:本着与众多业内人士交流.传播思想的目的展示在此,原论坛的名称已经不记得了,当时亦是转载.你可以任意转载此文,但由此引起的任何道德.法律纠纷与http:blog.csdn.net/aceplus无关,且http:blog.csdn.net/aceplus保证没有将此文用作任何商业和非法用途:如果您是本文的原作者,认为http:blog.csdn.net/aceplus转载

100TB级, 日增量1TB(100亿), OLTP OLAP混合场景数据库设计方向

标签 PostgreSQL , LLVM , JIT , 并行 , 列存储 , GPU , 向量计算 , HLL , 流计算 , OSS对象存储结合   背景 总量100TB,日增量1TB(日增约100亿记录)左右.这样的体量应该可以覆盖目前绝大多数企业的数据库体量. 提到100TB级别,OLTP和OLAP的混合场景,大家可能会想到Oracle的一体机extradata,没错Oracle在这方面做得确实是非常棒的,但是价格也是很漂亮的. Oracle主要通过几个方面来提升它在这个级别的性能: 共

贷款、天使投资(风控助手)业务数据库设计 - 阿里云RDS PostgreSQL, HybridDB for PostgreSQL最佳实践

标签 PostgreSQL , HybridDB for PostgreSQL , 小微贷款 , 金融风控 , 企业图谱 , 图式搜索 , 舆情分析 , 自动贷款 , 贷款审查 , 审查神器 背景 贷款是银行的主营业务之一,但是并不是只有银行能提供贷款,实际上资金雄厚的公司都有能力提供贷款(比如保险行业.资源垄断型企业等). 除了放贷,我们常说的天使投资.A轮B轮啥的,也是类似的场景,凭什么投你,背后如何决策也需要决策系统的支撑. 与贷款相反的是吸金类业务,比如我们现在发现越来越多的理财产品.股

数据库设计指南之我见

网上流传着一份关于数据库设计的文档<数据库设计指南>收集了几十个数据库设计大牛在项目中总结出来的Best Practice最佳实践,我最近也花了点时间细读并结合自身实际进行了总结,感觉自己在项目中还是有不少不足的地方,下面逐条分析下.(黑字为原文,红字为我的见解) 数据库设计指南 如果把企业的数据比做生命所必需的血液,那么数据库的设计就是应用中最重要的一部分.有关数据 库设计的材料汗牛充栋,大学学位课程里也有专门的讲述.不过,就如我们反复强调的那样,再好的 老师也比不过经验的教诲.所以我们最近