17 | 如何正确地显示随机消息?
17 | 如何正确地显示随机消息?
讲述:林晓斌
时长16:28大小15.04M
内存临时表
磁盘临时表
随机排序方法
小结
上期问题时间
赞 112
提建议
精选留言(176)
- 老杨同志置顶2018-12-21对应单词这种总量不是很多的数据,第一感觉应该装jdk缓存或者redis缓存。由于需要随机访问,数组比较好。假如一个单词平均10个字节,10*10000,不到1M就装下了。 如果一定要用数据库来做,老师的方案1比较好,空洞的问题,如果单词库不变,可以在上线前整理数据,把空洞处理调。比如:原来单词存在A表,新建B表 ,执行 insert into B(word) select word from A. B的id是自增的,就会生成连续的主键。当然如果A表写比较频繁,且数据量较大,业务上禁用 这种写法,RR的隔离级别会锁A表展开
作者回复: 重新整理表这个思路很赞👍🏿 看得出你是业务经验很丰富啊,这几次问题,对底层实现和业务功能的平衡,考虑点很不错
共 7 条评论274 - 雪中鼠置顶2018-12-21如果按照业务需求,随机取三个,数据库还在设计阶段,可以增加一个主键字段,用来记录每行记录的rowid,这样一万行,那就是连续的一万,然后随机,用该随机rowid回表查询该行记录
作者回复: 这个也是个好方法,就是确保连续,可以快速的得到C和几个偏移量
共 3 条评论29 - HuaMax2018-12-21假设Y1,Y2,Y3是由小到大的三个数,则可以优化成这样,这样扫描行数为Y3 id1 = select * from t limit @Y1,1; id2= select * from t where id > id1 limit @Y2-@Y1,1; select * from t where id > id2 limit @Y3 - @Y2,1;
作者回复: 👍🏿
共 8 条评论143 - 大白给小白讲故事2018-12-21为什么随机算法2比order by rand()的代价小很多? 因为随机算法2进行limit获取数据的时候是根据主键排序获取的,主键天然索引排序。获取到第9999条的数据也远比order by rand()方法的组成临时表R字段排序再获取rowid代价小的多。
作者回复: 对的, 你是第一个回答正文中间问题的😄👍🏿
共 5 条评论95 - 吴宇晨2018-12-21我觉得可以按Y排个序,第一条取完,拿到对应id,然后有一条语句就是where id大于xxx,limit y2-y1,1
作者回复: 抓住了关键点👍🏿
共 4 条评论91 - 倪大人2018-12-21课后题可以在随机出Y1、Y2、Y3后,算出Ymax、Ymin 再用 select id from t limit Ymin,(Ymax - Ymin); 得到id集后算出Y1、Y2、Y3对应的三个id 最后 select * from t where id in (id1, id2, id3) 这样扫描的行数应该是C+Ymax+3
作者回复: 漂亮
共 18 条评论37 - 大神仙2019-02-20老师,limit n order by 非索引字段 进行分页查询。数据库符合条件的count=147000条,分页查询count也正确,但是分页查询出的147000条数据中存在重复数据。 1,这个我看网上解释是因为堆排序算法不稳定导致的。这个说法是否正确。 2,我查了很多资料,没找到,或者您能给我个指导,我去查查
作者回复: 我的理解是说, 你碰到了这种情况: limit n, a; 显示a条记录; 然后 limit n+a, a显示第二组a条件记录; 这两组a个记录出现了重复数据对吧, 是的,是因为limit 有可能出现两种算法,比如直接排序和优先队列排序,就是不同的结果。 而limit 后面的参数,是会影响算法的
共 13 条评论26 - 梦康2019-02-13翻了下评论,没人问优先队列排序里的 row_size 和 rows_estimate 是如何计算的。想了半天没想明白。
作者回复: 帮你贴下你自己的答案哈 https://mengkang.net/1338.html
共 3 条评论22 - 王飞洋2018-12-21归并排序,优先队列,算法无处不在。
作者回复: 要说算法还是隔壁王老师讲的专业,这里咱们就只追求MySQL 里面用到的,能给大家讲明白就行了😄
共 3 条评论22 - 慧鑫coming2018-12-21又到周五了,开心😜21
- freesia2018-12-23从上一讲到这一讲,我发现老师在处理问题时,提出的方法就不再是单纯依靠MySQL解决,因为可能会耗费很多资源,而是把问题分担一部分到客户端,比如客户端拿到数据后再排序,或者客户端产生随机数再到MySQL中去查询。
作者回复: 嗯嗯,MySQL 的代码和业务代码都是代码😄 配合起来用
共 2 条评论18 - Mr.Strive.Z.H.L2018-12-29老师你好,回顾这篇的时候突然有个疑惑。 执行器只是调引擎接口获取结果,但是我认为order by的排序过程应该是在执行器执行的吧?内存临时表使用的memory引擎,应该也是在server端,而磁盘临时表应该是innodb内部。 我这么理解对吗?还是说整个排序过程全部都在innodb内部执行? 对此突然有点疑惑………展开
作者回复: mysql的执行过程都是由执行器来调度的 不论创建memory临时表还是innodb临时表,都是执行器调用引擎的创建表接口实现的 写数据和读数据也是 排序这个操作,是在server层做的
17 - 李皮皮皮皮皮2018-12-21我经常在文中看到多个事务的执行时序。线下做实验的时候,是怎么保证能按这个时序执行呢?
作者回复: 开两个窗口,按顺序执行命令哦
14 - Sinyo2019-02-13你可能会问,这里也用到了 limit,为什么没用优先队列排序算法呢?原因是,这条 SQL 语句是 limit 1000,如果使用优先队列算法的话,需要维护的堆的大小就是 1000 行的 (name,rowid),超过了我设置的 sort_buffer_size 大小,所以只能使用归并排序算法。 老师,上面的limit 1000 不是才14000么?14000小于32768的还是优先队列排序算法把?这里是不是10000少写了个0呢?展开
作者回复: 没有少0哈 好问题 最小堆的维护代价比数组大,不只是14*1000哦
共 2 条评论9 - 胡楚坚2019-01-20老师,只要sort buffer 足够,就采用优先队列排序,而不用管到底是全字段排序还是rowid排序,对吗?
作者回复: 前提是有limit 子句哈
10 - 无眠2018-12-21一直比较疑惑什么情况下会产生临时表Using temporary,希望老师指点下
作者回复: 查询需要临时表,比如我们这个例子里,需要临时表来放rand()结果
共 3 条评论9 - 高枕2018-12-25老师,怎样让mysql使用优先队列排序法而不使用归并排序算法呢?
作者回复: 排序内存设大点😄
共 2 条评论8 - 奋斗心2019-02-0220000行是指:扫描10000行到内存临时表,还有10000行是随机排序吗
作者回复: 第一个10000是扫描原表,第二个10000是扫描内存表; 排序过程本身是不增加扫描行数的
7 - big-new2019-03-25您好,老师?请问全字段排序、rowid排序 与 临时文件算法(归并排序算法)、优先队列排序算法的 作用点分别在哪里?赶紧这两种概念分不清楚了。麻烦帮忙解答下疑惑~,谢谢?共 5 条评论6
- 某、人2018-12-23今天这个问题我的理解转换成sql是: mysql> select count(*) into @C from t1; set @Y = floor(@C * rand()); set @Y1 = floor(@C * rand()); set @Y2 = floor(@C * rand()); select LEAST(@Y,@Y1,@Y2) into @Y4; select GREATEST(@Y,@Y1,@Y2) into @Y6; select floor((@Y6+@Y4)/2) into @Y5; set @sql = concat("select id into @id from t1 limit ", @Y4, ",1"); set @sql1 = concat("select id into @id1 from t1 where id>@id limit ", @Y5-@Y4, ",1"); set @sql2 = concat("select id into @id2 from t1 where id>@id1 limit ", @Y6-@Y5, ",1"); prepare stmt from @sql; prepare stmt1 from @sql1; prepare stmt2 from @sql2; execute stmt; execute stmt1; execute stmt2; DEALLOCATE prepare stmt; DEALLOCATE prepare stmt1; DEALLOCATE prepare stmt2; select * from t1 where id in (@id,@id1,@id2); 感觉mysql不太适合处理随机数的问题,稍稍有点复杂。 不过这两节课收获很多,对order by排序理解又深入不少,原来堆排序是放limit m,m行如果比sort_buffer占用空间小,则先把m行放进数据集里,然后在把表里的数据一行一行取出来做比较。得出的结果,在根据MRR回表取数据。 老师,我有一个问题: 堆排序,如果比较的值是相等的情况下,会不会替换在sort_buffer里?我感觉是不会,如果不会才能解释得通排序值相等,id不等的情况,不管是大顶堆还是小顶堆,得到的结果集都是id相对更小的展开7