一、MySQL如何进行SQL调优?
我的回答:
面试官好!我想从SQL语句本身和数据库结构两方面来做MySQL的SQL调优。
首先会优化SQL写法,比如避免用SELECT *、减少子查询嵌套,用JOIN代替,还有合理使用索引,比如给查询频繁的字段建索引,同时避免索引失效的情况,像用函数操作索引列。
另外,会关注表结构设计,比如拆分大表、使用合适的数据类型。还会通过慢查询日志定位低效SQL,用EXPLAIN分析执行计划。我在学习中试过给查询频繁的字段加索引,查询效率确实提升了不少,这让我觉得调优能直接解决实际问题,所以也在持续积累这方面的经验,希望能更好地保证数据库性能。
回答重点官方答案:
平时进行调优,主要是观察慢SQL,然后利用explain分析查询语句的执行计划来优化查询语句。
1.合理设计索引,利用联合索引进行覆盖索引的优化,避免回表的发生,减少一次查询和随机I/0。
- 避免使用select *,只查询必要的字段
3.避免在SQL中进行函数计算等操作,使得无法命中索引。
4.避免使用前缀带 % 的模糊查询,导致全表扫描
5.注意联合索引需要满足最左匹配规则
6.不要对无索引字段进行排序操作
7.连表查询还要注意不同字段的字符集是否一致,否则也会导致全表扫描。
除此之外,还可以利用缓存来优化,一些变化少或者访问频繁的数据设置到缓存中,可以减轻数据库的压力,提升查询效率,还可以通过业务来优化,例如少展示一些不必要的字段,减少多表查询情况,将列表查询替换成分页分批查询等等。
若接着问explain执行计划中的各个字段


重点关注下面字段

二、如何使用MySQL的explain语句进行查询分析?
我的答案:
首先就是要在需要分析的SQL前加上explain,执行后会得到一张表,里面的字段能反映查询的关键信息,比如
看type字段,它表示连接类型,像const,eq_ref是比较好的。如果出现all就是全表扫描,就需要优化。
possible key字段是可能用到的索引。
key字段能看出实际用到的索引,如果是null就说明没走索引,此时要检查索引设计或SQL写法。
key_len是索引中使用的字节数,是索引字段最大可能长度,长度越短越好
rows字段大概估计要扫描的行数,数值越小越好。
我之前联系的时候,写了一个没有加索引的sql,用explain发现type是all,rows很大,加了索引之后,type变成ref,rows小了很多。查询速度快了很多。现在我每次写复杂sql都会先用explain分析一下,看是否有全表扫描、索引失效的情况,再针对性优化,慢慢的也更能理解索引和查询执行的关系了,以后会继续用这个工具提升SLQ效率
回答重点官方答案:
explain 主要用来 SQL 分析,它主要的属性详解如下:
- id :查询的执行顺序的标识符,值越大优先级越高。简单查询的 id 通常为 1,复杂查询(如包含子查询或 UNION)的 id 会有多个。
- select_type(重要):查询的类型,如 SIMPLE(简单查询)、PRIMARY(主查询)、SUBQUERY(子查询)等。
- table :查询的数据表。
- type(重要):访问类型,如 ALL(全表扫描)、index(索引扫描)、range(范围扫描)等。一般来说,性能从好到差的顺序是:const > eq_ref > ref > range > index > ALL。
- possible_keys :可能用到的索引。
- key(重要):实际用到的索引。
- key_len :用到索引的长度。
- ref :显示索引的哪一列被使用。
- rows(重要):估计要扫描的行数,值越小越好。
- filtered :显示查询条件过滤掉的行的百分比。一个高百分比表示查询条件的选择性好。
- Extra(重要):额外信息,如 Using index(表示使用覆盖索引)、Using where(表示使用 WHERE 条件进行过滤)、Using temporary(表示使用临时表)、Using filesort(表示需要额外的排序步骤)。
type 详解:
- system:表示查询的表只有一行(系统表)。这是一个特殊的情况,不常见。
- const:表示查询的表最多只有一行匹配结果。这通常发生在查询条件是主键或唯一索引,并且是常量比较。
- eq_ref:表示对于每个来自前一张表的行,MySQL 仅访问一次这个表。这通常发生在连接查询中使用主键或唯一索引的情况下。
- ref:MySQL 使用非唯一索引扫描来查找行。查询条件使用的索引是非唯一的(如普通索引)。
- range:表示 MySQL 会扫描表的一部分,而不是全部行。范围扫描通常出现在使用索引的范围查询中(如 BETWEEN、>,<,>=,<= )。
- index:表示 MySQL 扫描索引中的所有行,而不是表中的所有行。即使索引列的值覆盖查询,也需要扫描整个索引。
- all(性能最差):表示 MySQL 需要扫描表中的所有行,即全表扫描。通常出现在没有索引的查询条件中。
三、MySQL中的索引数量是否越多越好,为什么?
我的回答:
索引并不是越多越好,因为索引不论是从时间上还是空间上都是有一定成本的。
索引虽然能够加快查询速度,但会增加写操作(插入、更新、删除)的开销,每次增删改数据,不仅仅要修改表中数据,还要维护对应索引结构,索引越多,维护成本越高,可能拖慢写入性能。而且索引会占用额外的存储空间,太多的索引会浪费磁盘空间
另外查询时数据库可能会在多个索引中选择不合适的,反而影响查询效率。我之前试过给一张表加了多个索引,结果插入数据的速度明显慢了许多,所以索引要按需创建,要在查询和写入之间找平衡,所以我现在会根据实际查询场景合理建索引,避免盲目添加。
回答重点(官方答案)
索引并不是越多越好。因为索引不论从时间还是空间上都是有一定成本的
-
从时间上
每次对表中的数据进行增删改 (INSERT、UPDATE 或 DELETE) 的时候,索引也必须被更新,这会增加写入操作的开销。例如删除了一个 name 为张三的记录,不仅主键索引上需要修改,如果 name 字段有索引,那么 name 索引也需要修改,所以索引越多需要修改的地方也就越多,时间开销就大了,并且 B+ 树可能会有页分裂、合并等操作,时间开销就会更大。
还有一点需要注意:MySQL 有个查询优化器,它需要分析当前的查询,选择最优的计划,这过程就需要考虑选择哪个索引的查询成本低。如果索引过多,那么会导致优化器耗费更多的时间在选择上,甚至可能因为数据的不准确而选择了次优的索引。
-
从空间上
每建立一个二级索引,都需要新建一个 B+ 树,默认每个数据页都是 16KB,如果数据量很大,索引又很多,占用的空间可不小。