面向面试编程:MySQL调优——查询优化

128 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第11天,点击查看活动详情

面试官:查询数据的时候可以做哪些优化?

查询慢的原因

  • 网络
  • CPU
  • IO
  • 上下文切换
  • 系统调用
  • 生成统计时间
  • 锁等待时间

优化数据访问

查询性能低下的主要原因是访问的数据太多,某些查询不可避免的需要筛选大量的数据。我们可以通过减少访问数据量的方式进行优化。

减少访问量

  • 确认应用程序是否在检索大量超过需要的数据。
  • 确认MySQL服务器层是否在分析大量超过需要的数据行。

是否向数据库请求了不需要的数据

  • 查询不需要的记录。
  • 多表关联时返回全部列。
  • 总是取出全部列。
  • 重复查询相同的数据。

执行过程的优化

查询优化器

统计信息

  • 每个表或索引的页面个数。
  • 索引的基数。
  • 索引和数据行的长度。
  • 索引的分布情况。

MySQL选择错误执行计划的原因

  • 统计信息不准确。
  • 执行计划成本估算不等同于实际执行的成本。
  • MySQL的最优可能跟你想的不一样。
  • MySQL不考虑其他并发执行的查询。
  • MySQL不考虑不受其控制的操作成本。

优化器的优化策略

  • 静态优化:直接对解析树进行分析并完成优化。
  • 动态优化:与查询的上下文有关,也可能跟取值、索引对应的行数有关。
  • MySQL对查询的静态优化只有一次,但对动态优化每次执行时都要重新评估。

优化器的优化类型

  • 重新定义关联表的顺序。
  • 将外连接转化为内连接,内连接效率比外连接更高。
  • 使用等价变换规则,MySQL可以使用一些等价变换来简化并规划表达式。
  • 优化count(),min(),max()。
  • 预估并转化为常数表达式,当MySQL检测到一个表达式可以转化为常数时,就会一直把该表达式做为常数处理。
  • 索引覆盖扫描,当索引中的列包含所有查询中需要使用的列时,可以使用覆盖索引。
  • 子查询优化。
  • 等值传播。

优化特定类型的查询

优化count()查询

  • 总有人认为MyISAM的count函数比较快,但这是有前提条件的,只有不带任何where条件的count()才是比较快的。
  • 使用近似值。
  • 更复杂的优化。

优化关联查询

  • 确保on或using子句中的列上有索引,在创建索引的时候就要考虑到关联的顺序。
  • 确保任何的groupBy和orderBy中的表达式只涉及到表中的一个列,这样MySQL才有可能使用索引来优化这个过程。

优化limit分页

最简单的办法是尽可能使用覆盖索引,而不是查询全部的列。

优化union查询

除非确实需要服务器消除重复的行,否则一定要使用union all,因为没有all关键字,MySQL会在查询的时候给临时表加上distinct关键字,这个代价很高。