• QQ怪
    2019-08-10
    回答老师问题:
    按照老师的操作了一遍,实验小部分区间是会走order_id索引的,但是查询范围继续增大 ,反而不走索引而是全表扫描,大概我估摸着的是小于全表5分之一区间能够走索引,超过5分之一会全表扫描,可以使用force index(索引名)强制使用该索引,这就是有些sql表开始跑的挺快的,后面越来越慢的原因吧。。但不清楚mysql优化器为啥要这样选择,希望老师解惑?

    作者回复: 因为order_id索引不能覆盖我们要查询的信息,所以在对order_id查询之后还需要一次回表来查找到整行数据,虽然order_id索引是顺序存放的,但是相对于主键id存放的数据顺序是不一致的,所以存在每次回表都是随机获取整行数据,如果在获取大量数据时,通过这种方式获取数据性能肯定是不理想的。

    所以mysql一般判断在查询超过整个表20%的数据时,就会考虑使用聚族索引来查找数据,这种方式顺序读取数据的可能性要大于使用辅助索引的随机读。

    在查询少量数据的情况下,使用辅助索引性能更加,而查询大量数据时,就未必了。

    如果我们发现在查询一定量数据使用辅助索引要比主键索引快,而数据库又没有按照我们期望的去使用辅助索引,则我们可以通过子查询或force index来强制使用辅助索引。

     2
     22
  • CCC
    2019-08-10
    对索引进行函数操作或者表达式计算也会导致索引的失效

    作者回复: 对的,点赞补充

    
     6
  • 张三丰
    2019-10-04
    ”如果不存在辅助索引,此时会通过查询聚簇索引来统计行数,如果此时正好存在一个辅助索引,则会通过查询辅助索引来统计行数,减少 I/O 操作。“
    这有什么区别吗?都是通过索引统计行数

    作者回复: 区别在于聚簇索引存储了其他数据,而辅助索引只保存了索引列和主键,所以通过查询辅助索引统计行检索的数据量会更少,I/O操作会更少

    
     3
  • Charles
    2019-08-14
    想问下老师为什么回表查询的速度会慢于直接用主键查询,因为回表也是使用主键ID去查询的,就算查询的数据量大,用不用子查询都是使用主键ID去回表或是查询,速度应该一样吧

    作者回复: 回表就相当于两次索引树扫描操作了,而主键查询只有一次。

     1
     3
  • Geek__ad4af7fe01f4
    2019-08-27
    请问老师,既然使用辅助索引效率低,mysql默认超出20%又使用主键索引优化,而优化的效果又变低,为何还要强制使用辅助索引?

    这里强制使用辅助索引的优化 和下面您的描述不是冲突吗?

    因为order_id索引不能覆盖我们要查询的信息,所以在对order_id查询之后还需要一次回表来查找到整行数据,虽然order_id索引是顺序存放的,但是相对于主键id存放的数据顺序是不一致的,所以存在每次回表都是随机获取整行数据,如果在获取大量数据时,通过这种方式获取数据性能肯定是不理想
    展开

    作者回复: 这个跟具体场景有关系,在数据量非常大的情况下,可能使用辅助索引会效率更高些。

    
     2
  • 张学磊
    2019-08-10
    由于是select *操作,所以每条记录都需进行回表,当server层分析器发现between的范围太大时,使用辅助索引存在大量回表操作,所以觉得得不偿失,故而直接使用主键索引。如果想使用我们期望的索引,需要给server层分析器一个hint,force index(idx_order_id)

    作者回复: 分析到位,答案正确。

    
     2
  • 行者
    2020-01-03
    索引失效一句话总结,字段a有索引,那么只能匹配字段a,除此之外均会导致索引失效,比如所有对字段a的函数计算(如reverse、crc32),类型转换(如bigint转vachar,也就是SQL中有没有单引号),前置模糊搜索(like "%张三",因为后置模糊匹配可以使用前缀索引),where子句的多条件组合不当(需要根据情况的分析是否会用索引)

    作者回复: 赞

    
     1
  • 某、 
    2019-12-05
    使用某个字段中字符串的前几个字符建立索引?这句不是很明白,能否细讲一下,能否以身份证这个字段作个栗子?

    作者回复: 身份证前几位一般在相同城市或省都是一样的,所以作为前缀索引区分度不大,如果倒序存储,以原来后六位作为首位区分度更大,alert table xxx add index index_idno(idno(6));

    
     1
  • man1s
    2019-09-16
    走主键索引,优化器认为5000数据+回表5000次性能消耗要大于全表扫描
    force index

    作者回复: 👍

    
     1
  • Loubobooo
    2019-08-11
    我的想法是,可以利用子查询去减少回表操作,既然有主键自增id,便可以利用聚簇索引的优势来强制走索引。代码方法如下:select * from order_detail where id in (select id from order_detail where order_id between 5000 and 10000)

    作者回复: 思路是对的,这种方式可以解决。

    
     1
  • 天天向上
    2020-01-16
    如果查询条件中使用 or,且 or 的前后条件中有一个列没有索引,那么涉及的索引都不会被使用到。想知道为什么涉及到的索引都不会被用到,原理是什么呢?

    作者回复: 如果其中有一个没有索引,这个没有索引的列就会涉及到全表扫描

    
    
  • 天天向上
    2020-01-15
    SELECT COUNT(*) 时,如果不存在辅助索引,此时会通过查询聚簇索引来统计行数,如果此时正好存在一个辅助索引,则会通过查询辅助索引来统计行数,减少 I/O 操作。 这里说的正好存在一个辅助索引,指的是where条件中正好存在辅助索引吗?

    作者回复: 这里指的是无条件搜索,如果有条件搜索,则会根据搜索条件的索引来统计行数。

    
    
  • 天天向上
    2020-01-15
    在对“QQ怪”的回复中,老师说:在查询少量数据的情况下,使用辅助索引性能更加,而查询大量数据时,就未必了。为什么?

    作者回复: 因为辅助索引order_id索引不能覆盖我们要查询的信息,所以在对order_id查询之后还需要一次回表来查找到整行数据,虽然order_id索引是顺序存放的,但是相对于主键id存放的数据顺序是不一致的,所以存在每次回表都是随机获取整行数据,如果在获取大量数据时,通过这种方式获取数据性能肯定是不理想的。

    
    
  • 天天向上
    2020-01-14
    order 表中建立一个复合索引 idx_user_order_status(order_no, status, user_id),使用 order_no+user_id 组合查询,只有order_no会用到索引,user_id并不会
    
    
  • 阿杜
    2019-12-14
    status这种字段也需要加入到联合索引中吗?比如查询status和code,是建status+code的联合索引好还是只建立code索引?

    作者回复: 具体要看查询status的值的数据量,例如如果数据大部分是status=1的,而且我们也是查询status=1的数据,那建立status+code的联合索引就没有很大意义,这个时候建议只建立code索引就可以,如果我们是要查询少量status=0,这个时候我们需要建立status+code联合索引。

     1
    
  • 传传传传传传奇
    2019-11-05
    来晚了
    有一事不明,通过创建覆盖索引(如文中将商品编码、名称、价格作为一个组合索引)在某些情况下可以避免回表。但是非主键索引存储的却是主键的值,并以此来作为指向行的指针。在查询商品编码的时候,怎么理解避免回表吗?
    
    
  • 风轻扬
    2019-09-23
    老师,我试了一下最左匹配原则。按照您的例子试了一下,发现有的时候,and两端的表达式交换顺序,依然可以使用到复合索引。查了查,是因为mysql的优化器会自己优化。这是怎么回事呢?网上的解释没有看懂。。。。。。
     1
    
  • Demon.Lee
    2019-09-16
    Key Point:

    如果觉得这些规则太多,难以记住,我们就要养成经常检查 SQL 执行计划的习惯。
    
    
  • godtrue
    2019-09-14
    老师,请问存储引擎具体判断使用什么索引的原则是啥?大体的原则肯定是怎么快怎么走?不过也存在一定的误判,请问老师清楚误判的原因和具体都有那些场景嘛?

    作者回复: mysql查询优化是基于检索成本考虑,而不是基于时间成本考虑,假设我们读取的是随机行的数据,在磁盘中存储是无序的,有可能在扫描少数行的情况下,所需时间更长,这种情况下会出现误选择索引。

    通常在一些in操作时,在数据量比较小的情况下,会使用我们建立的索引,当数据量超过一定量时,会改走主键索引。我们一般是通过慢日志来排查这些问题,一旦发现不是走的我们想要的索引,可以使用force index来强制走期望的索引。

    
    
  • DY
    2019-09-10
    老师,你好。 select * from order_detail where id in (select id from order_detail where order_id between 5000 and 10000); 这种优化方式我试了试, 没起到什么优化作用。问了下DBA,说都回表了, 先查询主键ID也回表, 感觉和自己理解的不一样,但是又没法反驳。看了下执行计划这条sql也确实回表了

    作者回复: 我们这里讨论的是索引失效

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