索引失效情况
- 查询条件包含or,可能导致索引失效
- 如何字段类型是字符串,where时一定用引号括起来,否则索引失效
- like通配符可能导致索引失效。
- 联合索引,查询时的条件列不是联合索引中的第一个列,索引失效。
- 在索引列上使用mysql的内置函数,索引失效。
- 对索引列运算(如,+、-、*、/),索引失效。
- 索引字段上使用(!= 或者 < >,not in)时,可能会导致索引失效。
- 索引字段上使用is null, is not null,可能导致索引失效。
- 左连接查询或者右连接查询查询关联的字段编码格式不一样,可能导致索引失效。
- mysql估计使用全表扫描要比使用索引快,则不使用索引
复合索引,排序也算使用索引的顺序
复合索引,排序也要符合左原则
索引不适合场景
- 数据量少的不适合加索引
- 更新比较频繁的也不适合加索引
- 区分度低的字段不适合加索引(如性别)
强制和忽略索引
explain select CustName,count(1) c from WorkOrder force index(ix_date)
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
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使用低效的索引
select * from
tb_O force index(idx_create_time)
inner join tb_task_A
inner join tb_task_B
inner join tb_C
on ...
where
tb_O.create_time < '2017-08-23 00:00:00' and ...
前缀索引
如果字符串过大, 可以用前缀索引节省空间
如果前缀区分度太低, 可以考虑两种方式变通
- 倒叙存储
- 新建hash字段 alter table user add index index2(email(6))