面试:给我说说你平时是如何优化MySQL的?

1、explain

在MySQL优化的时候、我们使用最多的是explain查看 SQL 的执行计划

类型 解释
type 连接类型。一个好的SQL语句至少要达到range级别、杜绝出现all级别
key 使用到的索引名。如果没有选择索引,值是NULL。可以采取强制索引方式【force index】、这里可以用force index(),这个指令可以指定本次查询强制使用哪个索引,因为Mysql优化器的选择并不是最优的索引。
ken_len 索引长度。
rows 扫描列数。该值是个预估值。
extra 注意常见的不太友好的值有:Using filesort, Using temporary。

具体的参考文档:https://www.cnblogs.com/laowenBlog/p/12640755.html

2、SQL语句中IN包含的值不应过多

MySQL对于IN做了相应的优化,即将IN中的常量全部存储在一个数组里面,而且这个数组是排好序的。

但是如果数值较多,产生的消耗也是比较大的。

例如:select id from table_name where num in(1,2,3) 对于连续的数值,能用 between 就不要用 in 了;

再或者使用连接来替换。

3、SELECT语句务必指明字段名称

SELECT *增加很多不必要的消耗(cpu、io、内存、网络带宽);

增加了使用覆盖索引的可能性;

当表结构发生改变时,前断也需要更新。

所以要求直接在select 后面接上字段名。

4、当只需要一条数据的时候,使用limit 1

这是为了使EXPLAIN中type列达到const类型

5、如果排序字段没有用到索引,就尽量少排序

排序的字段、尽量加上索引。

6、如果限制条件中其他字段没有索引,尽量少用or

or两边的字段中,如果有一个不是索引字段,而其他条件也不是索引字段,会造成该查询不走索引的情况。

很多时候使用 union all 或者是union(必要的时候)的方式来代替“or”会得到更好的效果。

7、尽量用union all代替union

union和union all的差异主要是前者需要将结果集合并后再进行唯一性过滤操作;

这就会涉及到排序,增加大量的CPU运算,加大资源消耗及延迟。

当然,union all的前提条件是两个结果集没有重复数据。

8、不使用 order by rand()

MySQL RAND()函数调用可以在0和1之间产生一个随机数

order by rand() 随机查询取前几条记录。

优化前:

select id from `表名` order by rand() limit 3;

优化后:

select id from `表名` t1
join (select rand() * (select max(id) from `表名`) as nid) t2
on t1.id > t2.nid limit 3;

9、区分in和exists

select * from 表1 where id in ( select id from 表2 );
// 相当于
select * from 表1 where exists ( select * from 表2 where 表2.id = 表1.id );

区分 in 和 exists 主要是造成了驱动顺序的改变、这是性能变化的关键。

如果是exists,那么以外层表为驱动表、先被访问。

如果是in,那么先执行子查询。

所以:in 适合于外表大而内表小的情况。exists适合于外表小而内表大的情况。

10、区分 not in和not exists

推荐使用not exists,不仅仅是效率问题,not in可能存在逻辑问题。

// 原始SQL语句
select colname … from A表
where a.id not in (select b.id from B表)
// 优化后的SQL语句
select colname … from A表
Left join B表 on where a.id = b.id
where b.id is null

11、使用合理的分页以提高分页效率

// 原始SQL
select id,name from table_name limit 866613, 20;

使用如上SQL语句分页、随着表数据量的增加,直接使用limit分页查询会越来越慢。

优化的方法如下:

可以取前一页的最大行数的id,然后根据这个最大的id来限制下一页的起点。

比如此列中,上一页最大的id是866612。sql可以采用如下的写法。

select id,name from table_name where id > 866612 limit 20;

12、分段查询

在一些用户选择页面中,可能一些用户选择的时间范围过大,造成查询缓慢。

主要的原因是扫描行数过多。

这个时候可以通过程序,分段进行查询,循环遍历,将结果合并处理进行展示。

主要看数据问题:扫描的行数成百万级以上的时候就可以使用分段查询。

13、避免在 where 子句中对字段进行 null 值判断

对于null的判断会导致引擎放弃使用索引而进行全表扫描。

14、不建议使用%前缀模糊查询

例如:LIKE “%name”或者LIKE “%name%”;

这种查询会导致索引失效而进行全表扫描;但是可以使用LIKE “name%”。

那如何查询“%name%”呢?答案:使用全文索引。

在我们查询中经常会用到

select id,fnum,fdst from table_name where user_name like '%zhangsan%';

这样的语句,普通索引是无法满足查询需求的。

庆幸的是在MySQL中,有全文索引来帮助我们。

需要解决的前提条件:

表的类型必须是MyISAM、建立全文检索的字段类型必须是char,varchar,text;

创建全文索引的sql语法是:

ALTER TABLE `table_name` ADD FULLTEXT INDEX `idx_user_name` (`user_name`);
// 或者
CREATE fulltext INDEX index_name ON table_name(colum_name);

使用全文索引的sql语句是:

// 在SELECT的WHERE字句中用MATCH函数,
// 索引的关键词用AGAINST标识,
// IN BOOLEAN MODE是只有含有关键字就行,不用在乎位置,是不是起启位置.
SELECT * FROM articles WHERE MATCH (tags) AGAINST ('旅游' IN BOOLEAN MODE);

15、避免在where子句中对字段进行表达式操作

比如

SELECT user_id,user_project FROM table_name WHERE age*2 = 36;

中对字段就行了算术运算,这会造成引擎放弃使用索引,建议改成

SELECT user_id,user_project FROM table_name WHERE age = 36/2;

16、避免隐式类型转换

where 子句中出现 column 字段的类型和传入的参数类型不一致的时候发生的类型转换,建议先确定where中的参数类型。

17、对于联合索引来说,要遵守最左前缀法则

举列来说索引含有字段id,name,school;

可以直接用id字段,也可以id,name这样的顺序;

但是name,school都无法使用这个索引。

所以在创建联合索引的时候一定要注意索引字段顺序,常用的查询字段放在最前面。

18、必要时可以使用force index来强制查询走某个索引

有的时候MySQL优化器采取它认为合适的索引来检索sql语句,但是可能它所采用的索引并不是我们想要的。这时就可以采用force index来强制优化器使用我们制定的索引。

19、注意范围查询语句

对于联合索引来说,如果存在范围查询,比如between,>,<等条件时,会造成后面的索引字段失效。

20、关于JOIN优化

LEFT JOIN A表为驱动表

INNER JOIN MySQL会自动找出那个数据少的表作用驱动表

RIGHT JOIN B表为驱动表

注意:MySQL中没有full join,可以用以下方式来解决

select * from A left join B on B.name = A.name
where B.name is null
union all
select * from B;
尽量使用inner join,避免left join

参与联合查询的表至少为2张表,一般都存在大小之分。

如果连接方式是inner join,在没有其他过滤条件的情况下MySQL会自动选择小表作为驱动表;

但是left join在驱动表的选择上遵循的是左边驱动右边的原则,即left join左边的表名为驱动表。

合理利用索引:

被驱动表的索引字段作为on的限制字段。

利用小表去驱动大表

如果能够减少驱动表的话,减少嵌套循环中的循环次数,以减少 IO总量及CPU运算的次数。

巧用STRAIGHT_JOIN

inner join是由mysql选择驱动表,但是有些特殊情况需要选择另个表作为驱动表;

比如有group by、order by等「Using filesort」、「Using temporary」时。

STRAIGHT_JOIN来强制连接顺序;

在STRAIGHT_JOIN左边的表名就是驱动表,右边则是被驱动表。

在使用STRAIGHT_JOIN有个前提条件是该查询是内连接,也就是inner join。

其他链接不推荐使用STRAIGHT_JOIN,否则可能造成查询结果不准确。

面试:给我说说你平时是如何优化MySQL的?的更多相关文章

  1. 面试被问怎么排查平时遇到的系统CPU飙高和频繁GC,该怎么回答?

    处理过线上问题的同学基本上都会遇到系统突然运行缓慢,CPU 100%,以及Full GC次数过多的问题.当然,这些问题的最终导致的直观现象就是系统运行缓慢,并且有大量的报警.本文主要针对系统运行缓慢这 ...

  2. 面试技巧,如何通过索引说数据库优化能力,内容来自Java web轻量级开发面试教程

    上星期写了一个篇文章,数据库方面的面试技巧,如何从建表方面展示自己能力,承蒙管理员抬举,放入首页,也承蒙各位厚爱,两天内收获了将近770个点击,也一度进入48小时热榜. 为了感谢管理员和大家的支持,再 ...

  3. 面试官问我,为什么老司机建议MySQL列属性尽量用 NOT NULL ?

    本文阅读时间大约6分钟. 其实写这篇文章,也是来自一个知识星球读者的提问,他在二面的过程中被问到了,由于他简历中写道有 MySQL 调优经验,但这个问题没有回答好,二面被刷了. 其实我们刚学习 C 语 ...

  4. 【面经】面试官:如何以最高的效率从MySQL中随机查询一条记录?

    写在前面 MySQL数据库在互联网行业使用的比较多,有些小伙伴可能会认为MySQL数据库比较小,存储不了很多的数据.其实,这些小伙伴是真的不了解MySQL.MySQL的小不是说使用MySQL存储的数据 ...

  5. java面试一日一题:请讲下对mysql的理解

    问题:请讲下对mysql的理解 分析:该问题主要考察对mysql的理解,基本概念及sql的执行流程 回答要点: 主要从以下几点去考虑, 1.mysql的整体架构? 2.mysql中每一个组件的作用? ...

  6. Hive优化(面试宝典)(详细的九个优化)

    Hive优化(面试宝典) 1.1 hive的随机抓取策略 理论上来说,Hive中的所有sql都需要进行mapreduce,但是hive的抓取策略帮我们 省略掉了这个过程,把切片split的过程提前帮我 ...

  7. 面试BAT前先搞定这18道MySQL经典面试题(含答案解析)

    一.MySQL的复制原理以及流程 (1)复制基本原理流程 1. 主:binlog线程——记录下所有改变了数据库数据的语句,放进master上的binlog中: 2. 从:io线程——在使用start ...

  8. 【大厂面试05期】说一说你对MySQL中锁的了解?

    这是我总结的一个表格,是本文中涉及到的锁(因为篇幅有限就没有包括自增锁) 加锁范围 名称 用法 数据库级 全局读锁 执行Flush tables with read lock命令各整个库接加一个读锁, ...

  9. 面试官:小伙子,给我说一下mysql 乐观锁和悲观锁吧

    悲观锁介绍 悲观锁,正如其名,它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持保守态度,因此,在整个数据处理过程中, 将数据处于锁定状态.悲观锁的实现,往往依靠数据库 ...

随机推荐

  1. 常用css3选择器

    <div class="wrapper"> <p class="test1">1</p> <p class=" ...

  2. h5单页面布局

    前段时间做了一个PC端单页面应用 GitHub因为项目开始的比较仓促,加上本人前端经验特别少,虽然项目大体完成了,但是页面布局确成立它的硬伤...为了填补心里落差,专门做了一个h5的单页面布局,代码很 ...

  3. canvas初尝试

    最近学习了canvas,就拿它做了这么个小东西,感觉已经爱上canvas了.上代码 /* * @auhor : 开发部-前端组-李鑫超 * @property { tableData : {Array ...

  4. 零基础JavaScript编码(三)总结

    任务目的 在上一任务基础上继续JavaScript的体验 接触一下JavaScript中的高级选择器 学习JavaScript中的数组对象遍历.读写.排序等操作 学习简单的字符串处理操作 任务描述 参 ...

  5. Docker部署LAMP项目

    前言 之前我们学习了如何在Linux部署LAMP项目,今天我们来学习一下如何在Docker下部署LAMP项项目吧! Docker 要求 CentOS 系统的内核版本高于 3.10 ,查看本页面的前提条 ...

  6. HTML5 基础知识(1)——基本标签

    ## HTML**概念**:是最基础的网页开发语言(Hyper Text Markup Langage 超文本标记语言) > 1.超文本:超文本是用超链接的方式i,将各种不同空间的文字组织在一起 ...

  7. 2020 新个税算的头疼?会 python,这都不是事儿...

    背景 今年疫情复工后,财务小姐姐给我们普及了2020年新个税的算法.. 听完之后的感觉就是:恩,原来是这么回事! 虽然是个小工薪阶级,但是对于扣多少税还是很关心的.于是拿起笔算了算2月份的个税,产生了 ...

  8. ADO.NET连接数据库DBHelper工具类

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  9. flask 分页数据显示

    填充一些数据在表中 @blue.route('/pages/') def pages(): # 默认进入这个视图函数 第一页并只显示5条数据 page = request.args.get('page ...

  10. bug的前世今生

    项目上发现的产品bug,若本地有问题,那就是漏测 1.提到产品bug系统 2.需要追踪,要么是漏测,要么是改出来的问题,漏测的需要补充到测试点里 项目上发现的产品bug,若本地没问题,那就是项目上的产 ...