索引失效情况

  • 查询条件包含or,可能导致索引失效
  • 如何字段类型是字符串,where时一定用引号括起来,否则索引失效
  • like通配符可能导致索引失效。
  • 联合索引,查询时的条件列不是联合索引中的第一个列,索引失效。
  • 在索引列上使用mysql的内置函数,索引失效。
  • 对索引列运算(如,+、-、*、/),索引失效。
  • 索引字段上使用(!= 或者 < >,not in)时,可能会导致索引失效。
  • 索引字段上使用is null, is not null,可能导致索引失效。
  • 左连接查询或者右连接查询查询关联的字段编码格式不一样,可能导致索引失效。
  • mysql估计使用全表扫描要比使用索引快,则不使用索引

复合索引,排序也算使用索引的顺序
复合索引,排序也要符合左原则

索引不适合场景

  • 数据量少的不适合加索引
  • 更新比较频繁的也不适合加索引
  • 区分度低的字段不适合加索引(如性别)

强制和忽略索引

  1. explain select CustName,count(1) c from WorkOrder force index(ix_date)
  2. where CreateDate>'2016-5-1' and CreateDate<'2017-1-1' group by CustName having c>100 order by c desc;

假如我不想用索引了怎么办?

可以使用ignore index(),这个指令可以强制Mysql在查询时,不使用某索引

禁止使用查询缓存

sql_no_cache

  1. select sql_no_cache count(*) from roi_summary;

in和exists

in 是把外表和内表作hash 连接,
而exists是对外表作loop循环,每次loop循环再对内表进行查询。
一直以来认为exists比in效率高的说法是不准确的。
如果查询的两个表大小相当,那么用in和exists差别不大。
如果两个表中一个较小,一个是大表,则子查询表大的用exists,子查询表小的用in:


not in 和not exists如果查询语句使用了not in 那么内外表都进行全表扫描,没有用到索引;
而not extsts 的子查询依然能用到表上的索引。所以无论那个表大,用not exists都比not in要快。

groupby

  • groupby本质上是先排序后分组,遵照索引建的最左前缀
  • 当无法使用索引列,增大max_length_for_sort_data参数的设置+增大sort_buffer_size参数的设置
  • where高于having,能写在where限定的条件就不要去having限定了

force index

索引数据重复率太高会导致全表扫描:当表中索引字段数据重复率太高,则MySQL可能会忽略索引,进行全表扫描,此时使用表锁。可使用 force index 强制使用索引
还有避免mysql使用低效的索引

  1. select * from
  2. tb_O force index(idx_create_time)
  3. inner join tb_task_A
  4. inner join tb_task_B
  5. inner join tb_C
  6. on ...
  7. where
  8. tb_O.create_time < '2017-08-23 00:00:00' and ...

前缀索引

如果字符串过大, 可以用前缀索引节省空间
如果前缀区分度太低, 可以考虑两种方式变通

  • 倒叙存储
  • 新建hash字段 alter table user add index index2(email(6))