• 张学磊
    2019-08-06
    status和create_time单独建索引,在查询时只会遍历status索引对数据进行过滤,不会用到create_time列索引,将符合条件的数据返回到server层,在server对数据通过快排算法进行排序,Extra列会出现file sort;应该利用索引的有序性,在status和create_time列建立联合索引,这样根据status过滤后的数据就是按照create_time排好序的,避免在server层排序

    作者回复: 非常准确!

     3
     27
  • Kian.Lee
    2019-08-08
    我在实际项目中使用“select order_no from order where status =1 order by id desc
    ” 代替此功能,id为bigint ,也少维护一个索引(create_time)😁
     1
     5
  • QQ怪
    2019-08-06
    对staus和create_time建立联合索引

    作者回复: 对的,为了避免文件排序的发生。因为查询时我们只能用到status索引,如果要对create_time进行排序,则需要使用文件排序filesort。

    filesort是通过相应的排序算法将取得的数据在内存中进行排序,如果内存不够则会使用磁盘文件作为辅助。虽然在一些场景中,filesort并不是特别消耗性能,但是我们可以避免filesort就尽量避免。

     1
     4
  • Jian
    2019-08-12
    因为好久没有做SQL相关的开发了,所以开始没有特别明白【利用子查询优化分页查询】这里面的意思。我来说下自己的想法,请您检证。我看到您贴的截图中,优化后的sql语句,扫描的行数(rows列)分别是90409和10001,多余前一个较慢的查询,可见扫描行数,不是这个性能的主要原因。我推测这个是由于limit [m],n的实现方法导致的,即MySql会把m+n的数据都取出来,然后返回n个数据给用户。如果用第二种SQL语句,子查询只是获得一个id,虽然扫描了很多行,但都是在索引上进行的,切不需要回表获取内容。外查询是根据id获取数据20条内容,速度自然就会快了。我认为这里性能提高的原因还是居于索引的恰当使用。

    作者回复: 可以这么理解

    
     3
  • 迎风劲草
    2019-08-06
    创建 status create_time order_no 联合索引,避免回表

    作者回复: 建立联合索引没错,还有就是避免文件排序的问题。

     1
     2
  • 大俊stan
    2019-09-08
    count(*) 的速度是最快的innodb自己有优化
    
     1
  • mumu
    2019-11-04

    select * from `demo`.`order` where id> (select id from `demo`.`order` order by order_no limit 10000, 1) limit 20;,老师您好,我不懂这样写为什么是正确的,为什么id>子查询结果的20条就是按order_no排序所需的20条?

    作者回复: 这里我们就默认orderno是递增的,而且是随着id自增长递增

    
    
  • 张三丰
    2019-10-04
    就算使用了联合索引,也避免不了排序吧,因为题目要求的是降序,联合索引是保证第一个索引有序的前提下再保证第二个索引有序,那么这个有序是升序,如果没记错的话。

    作者回复: 只要有序的,就不会再重复排序了,只是一个升降序的问题了

    
    
  • 疯狂咸鱼
    2019-09-26
    为什么分页查询优化那块,主查询扫描这么多行?

    作者回复: 使用limit 10000,1,所以需要顺序扫描到10001行,所以我们尽量使用主键递增的方式,直接将主查询换成select * from `demo`.`order` where id> 10000 limit 20,避免扫描带来的性能问题。

    
    
  • 风轻扬
    2019-09-20
    select * from `demo`.`order` where id> (select id from `demo`.`order` order by order_no limit 10000, 1) limit 20;
    老师,这个优化后的查询,您是先查询出来的第10001条数据的id,然后 id 大于此值。获取20条数据。这样获取的值不对啊,我试了。这样获取的是10002到10021的数据了,不是10001到10020的数据。子查询获取的值减一就对了

    作者回复: >=即可,强调优化思路,具体的细节老师这边没有把控好,多多包涵

    
    
  • man1s
    2019-09-16
    创建create_time + status 的组合索引
    问:老湿,执行计划中的const/system 你说B+树的第一层就可以返回,可是只有叶子节点才存储数据呀

    作者回复: 这里解释的有问题,已修正,是一个匹配行。

    
    
  • godtrue
    2019-09-14
    课后思考及问题
    1:按照效率排序的话,count(字段)<count(主键 id)<count(1)≈count(*),所以我建议你,尽量使用 count(*)。——MySQL,丁奇老师的结论
    如果对一张大表经常做 SELECT COUNT(*) 操作,这肯定是不明智的。——刘老师的结论
    同样的问题,不同的老师给出了截然相反的结论,我希望有一天两位老师可以讨论一下为什么?
    刘老师具体没讲COUNT(*)的原理,我倾向于认为丁奇老师的结论是正确的。

    作者回复: 我与丁奇结论没有相反,丁奇是建议你在这些count类型中选择使用count(*),而我是建议不要在大表中做count(*)。丁奇老师讲解了COUNT(*)的原理,我相信他也会建议你不要在一个大表中频繁COUNT(*)。

     1
    
  • 张德
    2019-08-28
    没看别人评论 我来说一下 直接查状态为1的订单 索引的区分度太低

    作者回复: 答案已给出

    
    
  • 陈影
    2019-08-26
    select * from `demo`.`order` where id> (select id from `demo`.`order` order by order_no limit 10000, 1) limit 20;
    老师,这个子查询找到了按照order_no排序第10001行数据的id,这个id是按照这种排序递增的吗?主查询是怎么找到这种排序方式下第10001-10020行数据的?

    作者回复: 这个id是自增长id

    
    
  • JackJin
    2019-08-09
    感觉要建立联合索引,但不知具体原因

    作者回复: 为了避免文件排序的发生。因为查询时我们只能用到status索引,如果要对create_time进行排序,则需要使用文件排序filesort。

    
    
  • Geek_002ff7
    2019-08-09
    真实情况一般不会在status上单独建索引,因为status大部分都是重复值,数据库一般走全表扫描了,感觉漏讲了索引失效的情况

    作者回复: 下一讲则会讲到

    
    
  • 东方奇骥
    2019-08-08
    select * from `demo`.`order` order by order_no limit 10000, 20;
    select * from `demo`.`order` where id> (select id from `demo`.`order` order by order_no limit 10000, 1) limit 20; 老师,感觉自己没完全弄明白,就是用子查询快那么多,但是子查询里,不是也要扫描10001行?还是说子查询里只查了id,不需要回行,所以速度快?

    作者回复: 这个涉及到返回记录的大小,前者会返回10020条行记录,而后者只返回20条记录。

     2
    
  • LW
    2019-08-06
    order_no创建主键,status+create_time创建联合索引

    作者回复: 对的

     1
    
  • 撒旦的堕落
    2019-08-06
    订单状态字段的离散度很低 不适合做索引
    因为离散度低 而又没有分页 所以当表数据量大的时候 查询出来的数量也有可能很大
    创建时间倒序 可以换成主键倒序 去除掉时间字段的索引
    根据状态查询 个人觉得可以从业务入手 将相同状态的数据保存到一张表 想听听老师的意见

    作者回复: 这里主要是filesort问题

    
    
  • nimil
    2019-08-06
    select * from table limit 1 这种sql语句会走主键索引么,我看explain里边没有任何索引记录

    作者回复: 不会,没有使用到索引。

    
    
我们在线,来聊聊吧