博客
关于我
Mysql索引优化
阅读量:788 次
发布时间:2023-02-13

本文共 2191 字,大约阅读时间需要 7 分钟。

Mysql性能调优指南

索引优化

在实际项目中,索引的选择往往需要根据查询模式进行分析。传统的观点认为,在数据量小时不会走索引,而在数据量较大时会走索引。然而,事实并非如此。在MySQL中,大部分情况下>不会走索引,而是会走全表扫描,这与直觉相悖。然而,如果使用覆盖索引,可以直接使用索引获取所需数据,而无需回表操作。

索引下推(ICP优化)

MySQL 5.6版本引入了ICP(Index Condition Pushdown)优化,主要用于辅助索引。ICP优化可以在存储引擎层对辅助索引进行过滤,而不是将数据传输到应用层进行条件筛选。例如,创建一个辅助索引,索引字段包括name、age和position。对于SQL查询SELECT * FROM employees WHERE name LIKE 'LiLei%' AND age = 22 AND position = 'manager',只有name字段会被用于索引筛选,而age和position字段由于无序无法合理使用索引。

在MySQL 5.6及更早版本中,这类查询会依次通过辅助索引找到符合LIKE条件的记录,然后逐个回表检查age和position字段的条件。然而,ICP优化可以减少回表次数,从而提升性能。

如何选择合适的索引

在实际操作中,索引的选择需要综合考虑多个因素。以下是一些关键点:

  • 覆盖索引:使用覆盖索引可以避免回表操作,直接获取所需字段。
  • 联合索引:尽量创建联合索引,覆盖查询中的多个字段。
  • 避免小基数字段索引:如性别字段通常不需要索引。
  • 前缀索引:对于长字符串字段,建议使用前20个字符的前缀索引。
  • where和order by冲突:优先满足where条件,以减少排序成本。
  • 为了分析索引选择,MySQL提供了OPTIMIZER_TRACE工具。通过设置optimizer_trace=enabled,可以查看具体的索引选择过程。例如,执行EXPLAIN select * from employees where name > 'a';可以显示索引选择的具体情况。

    Order by与Group by优化

    在实际应用中,EXPLAIN工具的Extra列可以提供排序相关信息。Using index表示排序使用了索引,而Using filesort表示使用了文件排序。为了提升性能,应尽量在排序字段上创建索引,并遵循最左前缀原则。

    对于Group by,如果不需要排序,可以在GROUP BY中添加ORDER BY NULL来禁止排序,以减少额外开销。

    文件排序原理

    MySQL的文件排序机制包括单路排序和双路排序。单路排序适用于字段总长度小于max_length_for_sort_data(默认为1024字节),而双路排序则用于更大字段。

    • 单路排序:直接将满足条件的记录加载到sort buffer中进行排序。
    • 双路排序:先在sort buffer中加载排序字段和主键值,完成排序后再回表获取其他字段。

    max_length_for_sort_data默认为1024字节,如果字段总长度超过该值,会使用双路排序。

    创建索引的设计思路

    索引设计应遵循业务需求,建议在主体功能开发完成后分析相关SQL,确定索引策略。以下是一些设计原则:

  • 联合索引:尽可能覆盖查询中的where、order by和group by字段。
  • 最左前缀原则:确保索引字段的顺序能满足查询需求。
  • 避免小基数字段索引:如性别字段通常不需要索引。
  • 前缀索引:对长字符串字段使用前缀索引,通常取20个字符。
  • where和order by冲突:优先满足where条件。
  • Limit分页优化

    传统的LIMIT分页查询会读取所有数据再进行剪切,效率较低。优化方法如下:

  • 主键自增且连续:可以通过WHERE id > 10000直接获取所需数据。
  • 辅助索引:使用覆盖索引获取id字段,通过关联查询获取所需记录。
  • Join关联查询优化

    MySQL的关联查询算法包括Nested Loop Join(NLJ)和Block Nested Loop Join(BNL)。NLJ适用于关联字段有索引的情况,而BNL适用于无索引的情况。以下是两种算法的对比:

  • NLJ:从被驱动表中读取数据,逐行与驱动表匹配,效率较高。
  • BNL:将驱动表数据加载到join buffer中,批量处理被驱动表数据,减少磁盘读取次数。
  • 建议在关联字段有索引时优先使用NLJ,否则使用BNL。

    IN和EXIST优化

    在使用IN或EXIST子查询时,需注意小表驱动大表原则。一般建议IN子查询中的数据量不超过1000。对于EXISTS子查询,可以将子查询替换为SELECT 1,因为其执行过程与SELECT 1相同。

    COUNT(*)查询优化

    COUNT(*)查询在InnoDB中需要实时计算,建议通过以下方式优化:

  • 查询缓存:临时关闭查询缓存以获取真实执行时间。
  • 使用count(1)COUNT(1)效率略高于COUNT(*)
  • 维护表的总行数:通过额外的表维护行数,减少COUNT(*)查询的开销。
  • 对于字段有索引的情况,COUNT(*)效率高于COUNT(字段)COUNT(id)

    通过以上优化,可以显著提升MySQL的性能,特别是在处理复杂查询和大数据量时。

    转载地址:http://zadfk.baihongyu.com/

    你可能感兴趣的文章
    Mysql学习总结(59)——数据库分库分表策略总结
    查看>>
    Mysql学习总结(60)——并发量大、数据量大的互联网业务数据库设计规范总结
    查看>>
    Mysql学习总结(61)——MySQL优化之DBA级优化整理汇总
    查看>>
    Mysql学习总结(64)——Mysql配置文件my.cnf各项参数解读
    查看>>
    Mysql学习总结(66)——设置MYSQL数据库编码为UTF-8
    查看>>
    Mysql学习总结(69)——Mysql EXPLAIN 命令使用总结
    查看>>
    Mysql学习总结(6)——MySql之ALTER命令用法详细解读
    查看>>
    Mysql学习总结(71)——MySQL 重复记录查询与删除总结
    查看>>
    Mysql学习总结(73)——MySQL 查询A表存在B表不存在的数据SQL总结
    查看>>
    Mysql学习总结(77)——温故Mysql数据库开发核心原则与规范
    查看>>
    Mysql学习总结(78)——MySQL各版本差异整理
    查看>>
    Mysql学习总结(79)——MySQL常用函数总结
    查看>>
    Mysql学习总结(7)——MySql索引原理与使用大全
    查看>>
    Mysql学习总结(80)——统计数据库的总记录数和库中各个表的数据量
    查看>>
    Mysql学习总结(81)——为什么MySQL不推荐使用uuid或者雪花id作为主键?
    查看>>
    Mysql学习总结(82)——MySQL逻辑删除与数据库唯一性约束如何解决?
    查看>>
    Mysql学习总结(83)——常用的几种分布式锁:ZK分布式锁、Redis分布式锁、数据库分布式锁、基于JDK的分布式锁方案对比总结
    查看>>
    Mysql学习总结(84)—— Mysql的主从复制延迟问题总结
    查看>>
    Mysql学习总结(85)——开发人员最应该明白的数据库设计原则
    查看>>
    mysql安装卡在最后一步解决方案(附带万能安装方案)
    查看>>