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


    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%';查看索引的使用情况:

    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+树,重建索引。这个过程是十分消耗数据库性能的。
    • 区分度不大的字段上不宜建立索引。
    • 业务上具有唯一特性的字段,即使是多个字段的组合,也必须建成唯一索引。
    • 多表关联时,要保证关联字段上一定有索引。
    • 创建索引时避免以下错误观念:索引越多越好,认为一个查询就需要建一个索引;宁缺勿滥,认为索引会消耗空间、严重拖慢更新和新增速度;抵制唯一索引,认为业务的唯一性一律需要在应用层通过“先查后插”方式解决;过早优化,在不了解系统的情况下就开始优化。
  • 相关阅读:
    车牌号验证正则验证
    人民币转大写
    Base64 格式图片上传至服务器
    郭博分析modbus主机模式
    解决小BUG的罗列
    写flash时为什么需要先擦除?
    C语言的很吊的printf-----来自一个C语言竞赛题目
    ( # #@ ## 在define中的应用)或( 连接两个字符串或者两个数字、强制转化成单引号、强制转化成双引号 )附加字符串强制转化成数字
    IAR无法goto的解决办法
    link list
  • 原文地址:https://www.cnblogs.com/fanzou/p/15739888.html
Copyright © 2020-2023  润新知