SQL必知必会
陈旸
清华大学计算机博士
立即订阅
10179 人已学习
课程目录
已完结 49 讲
0/4登录后,你可以任选4讲全文学习。
开篇词 (1讲)
开篇词丨SQL可能是你掌握的最有用的技能
免费
第一章:SQL语法基础篇 (19讲)
01丨了解SQL:一门半衰期很长的语言
02丨DBMS的前世今生
03丨学会用数据库的方式思考SQL是如何执行的
04丨使用DDL创建数据库&数据表时需要注意什么?
05丨检索数据:你还在SELECT * 么?
06丨数据过滤:SQL数据过滤都有哪些方法?
07丨什么是SQL函数?为什么使用SQL函数可能会带来问题?
08丨什么是SQL的聚集函数,如何利用它们汇总表的数据?
09丨子查询:子查询的种类都有哪些,如何提高子查询的性能?
10丨常用的SQL标准有哪些,在SQL92中是如何使用连接的?
11丨SQL99是如何使用连接的,与SQL92的区别是什么?
12丨视图在SQL中的作用是什么,它是怎样工作的?
13丨什么是存储过程,在实际项目中用得多么?
14丨什么是事务处理,如何使用COMMIT和ROLLBACK进行操作?
15丨初识事务隔离:隔离的级别有哪些,它们都解决了哪些异常问题?
16丨游标:当我们需要逐条处理数据时,该怎么做?
17丨如何使用Python操作MySQL?
18丨SQLAlchemy:如何使用Python ORM框架来操作MySQL?
19丨基础篇总结:如何理解查询优化、通配符以及存储过程?
第二章:SQL性能优化篇 (18讲)
20丨当我们思考数据库调优的时候,都有哪些维度可以选择?
21丨范式设计:数据表的范式有哪些,3NF指的是什么?
22丨反范式设计:3NF有什么不足,为什么有时候需要反范式设计?
23丨索引的概览:用还是不用索引,这是一个问题
24丨索引的原理:我们为什么用B+树来做索引?
25丨Hash索引的底层原理是什么?
26丨索引的使用原则:如何通过索引让SQL查询效率最大化?
27丨从数据页的角度理解B+树查询
28丨从磁盘I/O的角度理解SQL查询的成本
29丨为什么没有理想的索引?
30丨锁:悲观锁和乐观锁是什么?
31丨为什么大部分RDBMS都会支持MVCC?
32丨查询优化器是如何工作的?
33丨如何使用性能分析工具定位SQL执行慢的原因?
34丨答疑篇:关于索引以及缓冲池的一些解惑
35丨数据库主从同步的作用是什么,如何解决数据不一致问题?
36丨数据库没有备份,没有使用Binlog的情况下,如何恢复数据?
37丨SQL注入:你的SQL是如何被注入的?
第三章:认识DBMS (7讲)
38丨如何在Excel中使用SQL语言?
39丨WebSQL:如何在H5中存储一个本地数据库?
40丨SQLite:为什么微信用SQLite存储聊天记录?
41丨初识Redis:Redis为什么会这么快?
42丨如何使用Redis来实现多用户抢票问题
43丨如何使用Redis搭建玩家排行榜?
44丨DBMS篇总结和答疑:用SQLite做词云
第四章:SQL项目实战 (3讲)
45丨数据清洗:如何使用SQL对数据进行清洗?
46丨数据集成:如何对各种数据库进行集成和转换?
47丨如何利用SQL对零售数据进行分析?
结束语 (1讲)
结束语 | 互联网的下半场是数据驱动的时代
SQL必知必会
登录|注册

43丨如何使用Redis搭建玩家排行榜?

陈旸 2019-09-11
上一篇文章中,我们使用 Redis 模拟了多用户抢票的问题,这里再回顾一下原理。我们通过使用 WATCH+MULTI 的方式实现乐观锁机制,对 ticket_count 这个键进行监视,当这个键发生变化的时候事务就会被打断,重新请求,这样做的好处就是可以保证事务对键进行操作的原子性,当然我们也可以使用 Redis 的 incr 和 decr 来实现键的原子性递增或递减。
今天我们用 Redis 搭建一个玩家的排行榜,假设一个服务器存储了 10 万名玩家的数据,我们想给这个区(这台服务器)上的玩家做个全区的排名,该如何用 Redis 实现呢?
不妨一起来思考下面几个问题:
MySQL 是如何实现玩家排行榜的?有哪些难题需要解决?
如何用 Redis 模拟 10 万名玩家数据?Redis 里的 Lua 又是什么?
Redis 如何搭建玩家排行榜?和 MySQL 相比有什么优势?

使用 MySQL 搭建玩家排行榜

我们如果用 MySQL 搭建玩家排行榜的话,首先需要生成 10 万名玩家的数据,这里我们使用之前学习过的存储过程来模拟。
为了简化,玩家排行榜主要包括 3 个字段:user_id、score、和 create_time,它们分别代表玩家的用户 ID、玩家的积分和玩家的创建时间。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《SQL必知必会》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(4)

  • Demon.Lee
    感觉用redis,最终还是需要结合程序以及MySQL来处理,因为排行榜展示,前端还是需要用户名的,光给个用户id不知道是谁,除非redis有序集合的member包含了用户id和name,请指正。

    作者回复: 通常一个功能用一种DBMS即可,所以会用到有序集合的member保存id和name。因为这些数据是需要高频访问的,所以放到redis中会更适合。如果想要查询更具体的数据,需要用户点击排行榜中的某个玩家的时候,可以使用MySQL来处理,比如查看这个玩家具体使用过哪些英雄,具体战绩如何等。

    2019-09-12
    2
    3
  • 石维康
    在生成数据时,把"temp = temp + create_time / 10000000000"换成 temp = temp +1 - create_time / 10000000000 哈哈
    2019-09-12
    2
  • ttttt
    注册时间排名靠后MySQL语法:create_time按照降序排列。
    SELECT (@rownum := @rownum + 1) AS user_rank, user_id, score, create_time
    FROM user_score, (SELECT @rownum := 0) b
    ORDER BY score DESC, create_time DESC
    2019-09-11
    1
  • felix
    咨询老师一个关于ip匹配的索引问题:
    有一个IP的库表,每一条记录了一个开始ip和结束ip,然后想批量匹配ip,查询为何没有用上“联合索引KEY `ip_range_int` (`start_int`,`end_int`) USING BTREE”?要怎么设置索引才有效?
    CREATE TABLE `t_dt_ip` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `start_ip` char(15) DEFAULT NULL,
      `end_ip` char(15) DEFAULT NULL,
      `location` varchar(100) DEFAULT NULL,
      `start_int` int(10) unsigned DEFAULT '0',
      `end_int` int(10) unsigned DEFAULT '0',
      PRIMARY KEY (`id`),
      KEY `ip_range` (`start_ip`,`end_ip`) USING BTREE,
      KEY `ip_range_int` (`start_int`,`end_int`) USING BTREE
    ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

    explain update t_tmp_ip t, t_dt_ip i
    set t.ip_id = i.id
    where INET_ATON(t.ip_address) between i.start_int and i.end_int;
    | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
    | 1 | UPDATE | t | NULL | ALL | NULL | NULL | NULL | NULL | 1000 | 100.00 | NULL |
    | 1 | SIMPLE | i | NULL | ALL | ip_range_int | NULL | NULL | NULL | 541942 | 11.11 | Range checked for each record (index map: 0xC) |

    甚至加上单个字段索引也没有用??
    alter table `t_dt_ip` add index indx_t_dt_ip_start_int (start_int);
    mysql> explain select * from t_dt_ip i join t_tmp_ip t on 1= 1 where t.ip_address >= i.start_int limit 1;
    | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
    | 1 | SIMPLE | t | NULL | ALL | NULL | NULL | NULL | NULL | 73126 | 100.00 | NULL |
    | 1 | SIMPLE | i | NULL | ALL | ip_range_int,indx_t_dt_ip_start_int | NULL | NULL | NULL | 541942 | 33.33 | Range checked for each record (index map: 0xC) |
    2019-09-14
收起评论
4
返回
顶部