3. mysql 索引命中规则及优化

摘要:
返回数据的比例超过30%前导模糊查询不能命中索引。where后字段执行计算,不会中索引利用覆盖索引进行查询,避免回表。单列索引不存null值,复合索引不存全为null的值,如果列允许为null,可能会得到“不符合预期”的结果集,所以,请使用notnull约束以及默认值。

1.什么是索引

“索引(在mysql中叫键 key),是存储引擎快速找到记录的一种数据结构。” --- 《高性能MySQL》,例如innodb引擎使用的就是B+树。

2.索引类型

命令:show index from table_name; 查看索引详情。

  • 主键索引 PRIMARY KEY: 一种特殊的唯一索引,不允许为null,一般建表时会创建主键,若不设置主键,
    默认会为每一行生成row_id,查询时row_id不会当作索引使用,所以建表时,建议设置主键。
  • 唯一索引 UNIQUE:唯一索引列的值必须唯一,但允许有空值(一般表字段建议设置为 not null)。如果是组合索引,组合值必须唯一。
    可以通过ALTER TABLE table_name ADD UNIQUE (column);创建唯一索引;
    可以通过ALTER TABLE table_name ADD UNIQUE (column1,column2);创建唯一组合索引;
  • 普通索引 INDEX:这是最基本的索引,它没有任何限制。可以通过ALTER TABLE table_name ADD INDEX index_name (column);创建普通索引;
  • 组合索引 INDEX:即一个索引包含多个列,多用于避免回表查询。可以通过ALTER TABLE table_name ADD INDEX index_name(column1,column2, column3);创建组合索引
  • 全文索引 FULLTEXT:也称全文检索,是目前搜索引擎使用的一种关键技术。可以通过ALTER TABLE table_name ADD FULLTEXT (column);创建全文索引

索引一经创建不能修改,如果要修改索引,只能删除重建。可以使用
DROP INDEX index_name ON table_name;删除索引。

3.索引设计原则

1)适合索引的列 出现在where,select子句
2)基数(整个集合中不同的个数)较小的类,索引效果较小,没必要建立索引,例如性别
3)使用短索引,如果长字段列建立索引,建议使用前缀索引,前缀的的位数,可以从区分度和节约索引空间考量
4)不可过度索引,结合业务适量使用。索引需要额外的磁盘空间,同时查询时会加载到内存中。在修改表时会修改甚至重新构建索引,索引列越多,这个时间越长。同时建议删除或插入数据时,不要在自增主键中间段做碎片化的操作。

4.索引优化

explain sql; 常用命令,查看优化器的执行计划

  • 返回数据的比例,explain sql时filtered字段。一般返回表中30%内的数据会走索引,超过就全表扫描。30%,只是一个大概的范围。
  • 回表,创建索引之后,索引会包含该列的值和对应行所在的主键id,列值作为键,主键id作为值。例如 select * from table where filed = ?;由于还需要其他的列,所以会回表,回到主键索引上的叶子节点(聚簇索引)获取全行的值。

1)优化实战

虽然数据库有索引,但是并不被优化器选择使用。我们可以通过 SHOW STATUS LIKE 'Handler_read%';查看索引的使用情况:
3. mysql 索引命中规则及优化第1张

Handler_read_key:如果索引正在工作,Handler_read_key的值将很高。
Handler_read_rnd_next:数据文件中读取下一行的请求数,如果正在进行大量的表扫描,值将较高,则说明索引利用不理想。

  • 如果MySQL估计使用索引比全表扫描还慢,则不会使用索引。返回数据的比例超过30%
  • 前导模糊查询不能命中索引 。EXPLAIN SELECT * FROM user WHERE name LIKE '%s%';
  • 数据类型出现隐式转换的时候不会命中索引 ,EXPLAIN SELECT * FROM user WHERE name=1;(name 是 varchar)
  • 复合索引的情况下,查询条件不包含索引列最左边部分(不满足最左原则),最左原则并不是说是查询条件的顺序,
    而是字段需要满足复合索引的最左匹配。
  • union、in、or都能够命中索引,建议使用in。查询的CPU消耗:or>in>union。 union all 拼接后允许重复值
  • 用or分割开的条件,如果or前的条件中列有索引,而后面的列中没有索引,那么涉及到的索引都不会被用到
  • 负向条件查询不能使用索引,可以优化为in查询。可以优化为in查询,但是前提是区分度要高,返回数据的比例在30%以内。
  • 范围条件查询可以命中索引。范围条件有:<、<=、>、>=、between等。
  • where 后 字段执行计算,不会中索引
  • 利用覆盖索引进行查询,避免回表。
  • 建立索引的列,不允许为null。单列索引不存null值,复合索引不存全为null的值,如果列允许为null,可能会得到“不符合预期”的结果集,所以,请使用not null约束以及默认值。force index(filed)
    select * from t force index(a) where (a between 1 and 1000)

关于多个索引的选择

存在多个索引的情况下,优化器一般会通过比较扫描行数、是否需要临时表以及是否需要排序等,来作为选择索引的判断依据。也就是谁消耗少,就用谁。同时也可强制使用某个索引。

总结

  • 更新十分频繁的字段上不宜建立索引:因为更新操作会变更B+树,重建索引。这个过程是十分消耗数据库性能的。
  • 区分度不大的字段上不宜建立索引。
  • 业务上具有唯一特性的字段,即使是多个字段的组合,也必须建成唯一索引。
  • 多表关联时,要保证关联字段上一定有索引。
  • 创建索引时避免以下错误观念:索引越多越好,认为一个查询就需要建一个索引;宁缺勿滥,认为索引会消耗空间、严重拖慢更新和新增速度;抵制唯一索引,认为业务的唯一性一律需要在应用层通过“先查后插”方式解决;过早优化,在不了解系统的情况下就开始优化。

免责声明:文章转载自《3. mysql 索引命中规则及优化》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇JSTL fmt:formatNumber 数字、货币格式化国内云存储对比: 阿里云、腾讯云、Ucloud、首都在线下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Infobright数据库使用

最近公司要做一个用户访问日志记录统计分析的功能,需要记录日志,但是公司的产品一天大概产生百万级的日志信息, 本身日志记录信息就比较固化和简单(基本不会存在改动),平时没有什么用,就是在统计分析时需要查用一下,另外日志需要长期存储不删除! 于是问题的难点是:如何存储大量的日志信息和在此基础上做查询分析。 日志量:1天100万,一个月就是3000万,数据量大,...

MySQL体系结构以及各种文件类型学习

1,mysql体系结构 由数据库和数据库实例组成,是单进场多线程架构。 数据库:物理操作系统文件或者其它文件的集合,在mysql中,数据库文件可以是frm、myd、myi、ibd等结尾的文件,当使用ndb存储引擎时候,不是os文件,是存放于内存中的文件。 数据库实例:由数据库后台进程/线程以及一个共享内存区组成,共享内存可以被运行的后台进程/线程所共享。...

mysql索引类型 normal, unique, full text

问题1:mysql索引类型normal,unique,full text的区别是什么? normal:表示普通索引 unique:表示唯一的,不允许重复的索引,如果该字段信息保证不会重复例如身份证号用作索引时,可设置为unique full textl: 表示 全文搜索的索引。 FULLTEXT 用于搜索很长一篇文章的时候,效果最好。用在比较短的文本,如果...

pg10、11、12版本特性

2. 分区表的改进 PostgreSQL 10 实现了声明式分区,PostgtreSQL 11完善了功能,PostgreSQL 12提升了性能。我们知道在PostgreSQL 9.X时代需要通过表继承实现分区,这时还需要手工加触发器或规则把新插入的数据重新定向到具体的分区中,从PostgreSQL 10之后不需要这样了,直接用声明式分区就可以了,语法如下:...

zabbix安装教程

1.下 载 https://www.zabbix.com/download 往下拉选择到源码版本下载 2.创建zabbix用户 zabbix需要以非root用户运行;如果以root用户运行那么他将会自动切换到zabbix用户,如果zabbix用户不存在那么运行将会不成功 useradd -U zabbix root启动而没有zabbix时报错如下: za...

mysql事件机制——定时任务

定时任务是老生常谈了,因为我们总是需要定时修改特定的数据。 实现它的方法肯定不止一种,但我在相当长一段时间里都是用程序编码去做的,今天突然想到“为什么一定要采用调用的方式?”,用数据库自身的能力去实现不是更好么? 通过了解,mysql的事件机制可以完成定时任务,其原理是在指定的时间调用指定的存储过程。现在很简单了不是?开搞。 首先,我们需要一个存储过程,虽...