MySQL索引建立选择和常见失效原因总结,这些你都得知道

推荐阅读

索引建立选择

适合建立索引

  • 主键自动建立唯一索引( primary)
  • 频繁作为查询条件的字段应该创建索引 (比如银行系统银行帐号,电信系统的手机号)
  • 查询中与其它表关联的字段,外键关系建立索引 ( 比如员工,部门外键)
  • where条件里用到的字段
  • 查询中排序的字段,排序的字段若通过索引去访问将大提升排序速度( 索引能够提高检索的速度和排序的速度)
  • 查询中统计或分组的字段 (分组的前提是必排序)

不适合建立索引

  • 记录比较少
  • 频繁更新的字段不适合建立索引 (每次更新不单单更新数据,还要更新索引)
  • where条件里用不到的字段不建立索引
  • 经常增删改的表:索引提高了查询的速度,同时却会降低更新表的速度,如果对表的INSERT,UPDATE和DELETE。因为建立索引后, 更新表时, MYSQL不仅要保存数据,还要保存一下索引文件
  • 数据重复的表字段:如果某个数据列包含了许多重复的内容,为它建立索引 就没有太大在的实际效果。比如表中的某一个字段为国籍,性别数据的差异率和重复率不高,这种建立索引就没有太多意义

索引失效原因

使用索引注意

  • 越小的数据类型通常更好:越小的数据类型通常在磁盘、内存和CPU缓存中都需要更少的空间,处理起来更快。
  • 简单的数据类型更好:整型数据比起字符,处理开销更小,因为字符串的比较更复杂。在MySQL中,应该用内置的日期和时间数据类型,而不是用字符串来存储时间;以及用整型数据类型存储IP地址。
  • 尽量避免NULL:应该指定列为NOT NULL,除非你想存储NULL。在MySQL中,含有空值的列很难进行查询优化,因为它们使得索引、索引的统计信息以及比较运算更加复杂。你应该用0、一个特殊的值或者一个空串代替空值。
  • 索引不会包含有NULL值的列。

索引不能使用排查

  • 如果是同样的sql语句,在之前能够使用到索引,那么现在使用索引不起作用,以下几种主要情况:
    • 随着表的增长,where条件出来的数据太多,大于15%,使得索引失效(会导致CBO计算走索引花费大于走全表)
    • 统计信息失效,需要重新搜集统计信息
    • 索引本身失效,需要重建索引

不会用到索引

下面是一些不会使用到索引的原因

  • 没有查询条件,或者查询条件没有建立索引;

  • 在查询条件上没有使用引导列

  • 查询的数量是大表的大部分,大于是30%以上。

  • 索引本身失效

  • 在索引列上使用mysql的内置函数

  • 对小表查询,数据量小

  • CBO计算走索引花费过大的情况。其实也包含了上面的情况,这里指的是表占有的block要比索引小。

  • 隐式转换导致索引失效.这一点应当引起重视.也是开发中经常会犯的错误. 由于表的字段tu_mdn定义为varchar2(20), 但在查询时把该字段作为number类型以where条件传给mysql,这样会导致索引失效.

    错误的例子:select * from test where tu_mdn=13333333333;  
    正确的例子:select *	from test where tu_mdn='13333333333';
    
  • 对索引列进行运算导致索引失效,所指的对索引列进行运算包括(+,-,*,/,! 等)

    错误的例子:select * from test where id-1=9; 
    正确的例子:select * from test where id=10; 
    
  • 使用mysql内部函数导致索引失效.对于这样情况应当创建基于函数的索引.

    错误的例子:select * from test where round(id)=10; 说明,此时id的索引已经不起作用了 
    正确的例子:首先建立函数索引, create index test_id_fbi_idx on test(round(id)); 
    		  然后 select * from test where round(id)=10; 这时函数索引起作用了
    
  • 如果MySQL估计使用索引比全表扫描更慢,则不使用索引。

    例如如果列key_part1均匀分布在1100之间,查询时使用索引就不是很好
    select * from table_name where key_part1>1 and key_part<90;
    
  • 如果使用MEMORY/HEAP表并且where条件中不使用“=”进行索引列,那么不会用到索引。Heap表只有在“=”的条件下会使用索引。因为用的是哈希索引。

  • 用or分割开的条件,如果or前的条件中的列有索引,而后面的列中没有索引,那么涉及的索引都不会被用到。

  • 如果将要使用的索引列不是复合索引列表中的第一部分,则不会使用索引。(索引的最左匹配原则)

  • 如果like是以%开始,虽然在name上面建有索引,但是由于where 条件中like的值的“%”在第一位了,那么MySQL也会采用这个索引。

  • 如果WHERE子句的查询条件里使用了比较操作符LIKE和REGEXP,MYSQL只有在搜索模板的第一个字符不是通配符的情况下才能使用索引。比如说,如果查询条件是LIKE ‘abc%’,MYSQL将使用索引;如果条件是LIKE ‘%abc’,MYSQL将不使用索引。

  • 在JOIN操作中(需要从多个数据表提取数据时),MYSQL只有在主键和外键的数据类型相同时才能使用索引,否则即使建立了索引也不会使用

  • 在ORDER BY操作中,MySQL只有在排序条件不是一个查询条件表达式的情况下才使用索引。尽管如此,在涉及多个数据表的查询里,即使有索引可用,那些索引在加快ORDER BY操作方面也没什么作用。

  • 如果某个数据列里包含着许多重复的值,就算为它建立了索引也不会有很好的效果。比如说,如果某个数据列里包含了净是些诸如“0/1”或“Y/N”等值,就没有必要为它创建一个索引。

  • 如果对大的文本进行搜索,使用全文索引而不使用like“%…%”.

  • 不使用NOT IN和<>操作:NOT IN和<>操作都不会使用索引将进行全表扫描。NOT IN可以NOT EXISTS代替,id<>3则可使用id>3 or id<3来代替。

  • 排序的索引问题:MySQL查询只使用一个索引,因此如果where子句中已经使用了索引的话,那么order by中的列是不会使用索引的。因此数据库默认排序可以符合要求的情况下不要使用排序操作;尽量不要包含多个列的排序,如果需要最好给这些列创建复合索引。

  • 使用短索引:对串列进行索引,如果可能,应该指定一个前缀长度。例如,如果有一个CHAR(255)的列,如果在前10个或20个字符内,多数值是唯一的,那么就不要对整个列进行索引。短索引不仅可以提高查询速度而且可以节省磁盘空间和I/O操作。

  • 索引不会包含有NULL值的列:只要列中包含有NULL值都将不会被包含在索引中,复合索引中只要有一列含有NULL值,那么这一列对于此复合索引就是无效的。所以我们在数据库设计时不要让字段的默认值为NULL。

你知道的越多,你不知道的越多。
有道无术,术尚可求,有术无道,止于术。
如有其它问题,欢迎大家留言,我们一起讨论,一起学习,一起进步

发布了201 篇原创文章 · 获赞 129 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_40722827/article/details/105214794