• 老杨同志 置顶
    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表

    作者回复: 重新整理表这个思路很赞👍🏿

    看得出你是业务经验很丰富啊,这几次问题,对底层实现和业务功能的平衡,考虑点很不错

     2
     81
  • 雪中鼠 置顶
    2018-12-21
    如果按照业务需求,随机取三个,数据库还在设计阶段,可以增加一个主键字段,用来记录每行记录的rowid,这样一万行,那就是连续的一万,然后随机,用该随机rowid回表查询该行记录

    作者回复: 这个也是个好方法,就是确保连续,可以快速的得到C和几个偏移量

    
     7
  • 吴宇晨
    2018-12-21
    我觉得可以按Y排个序,第一条取完,拿到对应id,然后有一条语句就是where id大于xxx,limit y2-y1,1

    作者回复: 抓住了关键点👍🏿

     3
     33
  • HuaMax
    2018-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;

    作者回复: 👍🏿

     1
     29
  • 岁月安然
    2018-12-21
    为什么随机算法2比order by rand()的代价小很多?
    因为随机算法2进行limit获取数据的时候是根据主键排序获取的,主键天然索引排序。获取到第9999条的数据也远比order by rand()方法的组成临时表R字段排序再获取rowid代价小的多。

    作者回复: 对的,

    你是第一个回答正文中间问题的😄👍🏿

    
     27
  • 慧鑫coming
    2018-12-21
    又到周五了,开心😜
    
     13
  • 倪大人
    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

    作者回复: 漂亮

     6
     11
  • freesia
    2018-12-23
    从上一讲到这一讲,我发现老师在处理问题时,提出的方法就不再是单纯依靠MySQL解决,因为可能会耗费很多资源,而是把问题分担一部分到客户端,比如客户端拿到数据后再排序,或者客户端产生随机数再到MySQL中去查询。

    作者回复: 嗯嗯,MySQL 的代码和业务代码都是代码😄 配合起来用

    
     9
  • 梦康
    2019-02-13
    翻了下评论,没人问优先队列排序里的 row_size 和 rows_estimate 是如何计算的。想了半天没想明白。

    作者回复: 帮你贴下你自己的答案哈 https://mengkang.net/1338.html

    
     8
  • 李皮皮皮皮皮
    2018-12-21
    我经常在文中看到多个事务的执行时序。线下做实验的时候,是怎么保证能按这个时序执行呢?

    作者回复: 开两个窗口,按顺序执行命令哦

    
     8
  • 王飞洋
    2018-12-21
    归并排序,优先队列,算法无处不在。

    作者回复: 要说算法还是隔壁王老师讲的专业,这里咱们就只追求MySQL 里面用到的,能给大家讲明白就行了😄

    
     8
  • 无眠
    2018-12-21
    一直比较疑惑什么情况下会产生临时表Using temporary,希望老师指点下

    作者回复: 查询需要临时表,比如我们这个例子里,需要临时表来放rand()结果

    
     6
  • big-new
    2019-03-25
    您好,老师?请问全字段排序、rowid排序 与 临时文件算法(归并排序算法)、优先队列排序算法的 作用点分别在哪里?赶紧这两种概念分不清楚了。麻烦帮忙解答下疑惑~,谢谢?
     3
     3
  • 大神仙
    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 后面的参数,是会影响算法的

    
     3
  • Sinyo
    2019-02-13
    你可能会问,这里也用到了 limit,为什么没用优先队列排序算法呢?原因是,这条 SQL 语句是 limit 1000,如果使用优先队列算法的话,需要维护的堆的大小就是 1000 行的 (name,rowid),超过了我设置的 sort_buffer_size 大小,所以只能使用归并排序算法。

    老师,上面的limit 1000 不是才14000么?14000小于32768的还是优先队列排序算法把?这里是不是10000少写了个0呢?

    作者回复: 没有少0哈

    好问题

    最小堆的维护代价比数组大,不只是14*1000哦

    
     3
  • 胡楚坚
    2019-01-20
    老师,只要sort buffer 足够,就采用优先队列排序,而不用管到底是全字段排序还是rowid排序,对吗?

    作者回复: 前提是有limit 子句哈

    
     3
  • Mr.Strive.Z.H.L
    2018-12-29
    老师你好,回顾这篇的时候突然有个疑惑。
    执行器只是调引擎接口获取结果,但是我认为order by的排序过程应该是在执行器执行的吧?内存临时表使用的memory引擎,应该也是在server端,而磁盘临时表应该是innodb内部。
    我这么理解对吗?还是说整个排序过程全部都在innodb内部执行?
    对此突然有点疑惑………

    作者回复: mysql的执行过程都是由执行器来调度的

    不论创建memory临时表还是innodb临时表,都是执行器调用引擎的创建表接口实现的

    写数据和读数据也是

    排序这个操作,是在server层做的

    
     3
  • 某、人
    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相对更小的
    展开
    
     3
  • daydaynobug
    2019-04-23
    老师,在sort_buffer中排序总是会使用快排吗,这个跟待排序的数据量有关系吗,会不会使用其他的排序算法啊

    作者回复: 都在内存的话就用快排

    需要用到文件的话,有用到合并排序

    
     2
  • 阿狸爱JAVA
    2019-01-31
    感觉老师的思路很宽广,就像一个大宝藏,方案一不行还有方案二,方案二不行还有方案三,并且每个方案都能给出具体的性能比较与证据,而自己自能顺着老师的思路还能明白,可是一旦扩展开来,便大脑一片空白

    作者回复: 加油慢慢来哈~~😆

    
     2
我们在线,来聊聊吧