阿里一面:SQL 优化有哪些技巧?
Hollis的新书限时折扣中,一本深入讲解Java基础的干货笔记!
MySQL 相信大家一定都不陌生,但是不陌生不一定会用!
会用不一定能用好!
今天,Tom哥就带大家复习一个高频面试考点,SQL 优化有哪些技巧?
当然这个还是非常有实用价值的,工作中你也一定用的上。如果应用得当,升职加薪,指日可待
1、创建索引
一定要记得创建索引,创建索引,创建索引
重要的事说三遍!
执行没有索引的 SQL 语句,肯定要走全表扫描,慢是肯定的。
这种查询毫无疑问是一个慢 SQL 查询。
那么问题来了,是不是要收集所有的 where 查询条件,然后针对所有的组合都创建索引呢?
答案肯定是否定的。
MySQL 为了提升数据查询速率,采用 B+ 树结构,通过空间换时间
设计思想。另外每次对表数据做更新操作时,都要调整对应的 索引树
,执行效率肯定会受影响。
本着二八原则
,互联网请求读多写少
的特点,我们一定要找到一个平衡点。
阿里巴巴的开发者手册建议,单表索引数量控制在5个以内,组合索引字段数不允许超过5个
其他建议:
禁止给表中的每一列都建立单独的索引
每个Innodb表必须有个主键
要注意组合索引的字段的顺序
优先考虑覆盖索引
避免使用外键约束
2、避免索引失效
不要以为有了索引,就万事大吉。
殊不知,索引失效
也是慢查询的主要原因之一。
常见的索引失效的场景有哪些?
以 % 开头的 LIKE 查询
创建了组合索引,但查询条件不满足 '最左匹配原则'。如:创建索引 idx_type_status_uid(type,status,uid),但是使用 status 和 uid 作为查询条件。
查询条件中使用 or,且 or 的前后条件中有一个列没有索引,涉及的索引都不会被使用到
在索引列上的操作,函数 upper()等,or、!= (<>),not in 等
3、锁粒度
MySQL 的存储引擎分为两大类:MyISAM 和 InnoDB 。
MyISAM 支持表锁;InnoDB 支持行锁和表锁
更新操作时,为了保证表数据的准确性,通常会加锁,为了提高系统的高并发能力,我们通常建议采用 行锁
,减少锁冲突
、锁等待
的时间。所以,存储引擎通常会选择 InnoDB
行锁可能会升级为表锁,有哪些场景呢?
如果一个表批量更新,大量使用行锁,可能导致其他事务长时间等待,严重影响事务的执行效率。此时,MySQL会将
行锁
升级为表锁
行锁是针对索引加的锁,如果
条件索引失效
,那么行锁
也会升级为表锁
注意:行锁将锁的粒度缩小了,进而提高了系统的并发能力。但是也有个弊端,可能会产生死锁,需要特别关注。
4、分页查询优化
如果要开发一个列表展示页面并支持翻页时,我们通常会这样写 SQL
select * from 表 limit #{start}, #{pageSize};
随着翻页的深度加大, start
值越来越大,比如:limit 10000 ,10
看似只返回了 10 条数据,但数据库引擎需要查询 10010 条记录,然后将前面的 10000 条丢弃,最终只返回最后的 10 条记录,性能可想而知
针对这个问题,我们通常有另一种解决方案:
先定位到上一次分页的最大 id,然后对 id 做条件索引查询。由于数据库的索引采用 B+ 树结构,这样可以一步到位
select * from 表 where id > #{id} limit #{pageSize};
任何事情,有利就有弊
这种翻页方式只支持 上一页
、下一页
,不支持跨越式直梯翻页
上图是淘宝的商品搜索列表,为了用户体验更好,采用的也是 直梯式
翻页。
为了避免翻页过深,影响性能,产品交互上做了一些取舍,对总页数做了限制,最多支持 100 页。
方案二:采用子查询
select * from 表 where id > ( select id from 表 order by id limit 10000 1) limit 20;
将原来的单 SQL 查询拆成两步:
首先,查询出 一页数据中的最小 id
然后,通过 B+ 树,精确定位到
最小id的索引树节点位置
,通过偏移量
读取后面的 20条 数据
阿里的规约手册也有对应描述:
5、避免 select *
反面案例:
select * from 表 where buyer_id = #{buyer_id}
我们知道,MySQL 创建表后,具体的行数据存储在主键索引(属于聚簇索引)的叶子节点。
二级索引属于非聚簇索引,其叶子节点存储的是主键值
select * 的查询过程:
先在
buyer_id
的二级索引 B+ 树,查出对应的 主键 id 列表然后进行
回表
操作,在 主键索引中 查询 id 对应的行数据
所以,我们需要罗列清楚必须的查询字段,且字段尽量在 覆盖索引
中,从而减少 回表
操作。
6、EXPLAIN 分析 SQL 执行计划
授人以鱼不如授人以渔
除了知晓常见的不规范 SQL 写法,在开发过程中,避免踩坑
我们还应知道,出现了慢 SQL 该如何排查、优化
实验安排起来
创建表
CREATE TABLE `user` (`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',`income` bigint(20) NOT NULL COMMENT '收入',`expend` bigint(20) NOT NULL COMMENT '支出',PRIMARY KEY (`id`),KEY `idx_income` (`income`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='用户表';CREATE TABLE `biz_order` (`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',`user_id` bigint(20) NOT NULL COMMENT '用户id',`money` bigint(20) NOT NULL COMMENT '金额',PRIMARY KEY (`id`),KEY `idx_user_id` (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='订单表';
插入记录:
insert into user values(10,100,100);
insert into user values(20,200,200);
insert into user values(30,300,300);
insert into user values(40,400,400);insert into biz_order values(1,10,30);
insert into biz_order values(2,10,40);
insert into biz_order values(3,10,50);
insert into biz_order values(4,20,10);
比如下面的语句,我们看是否使用了索引,可以通过 explain
分析相应的执行计划
explain select * from user where id<20;
接下来,我们来逐一来说明每个字段的含义
id:每一次 select 查询都会生成一个 id,值越大,优先级越高,会被优先执行
select_type:查询类型,SIMPLE(普通查询,即没有联合查询、子查询)、PRIMARY(主查询)、UNION(UNION 中后面的查询)、SUBQUERY(子查询)等
table:查询哪张表
partitions:分区,如果对应的表存在分区表,那么这里就会显示具体的分区信息
type:执行方式,是 SQL 优化中一个很重要的指标,结果值从好到差依次是:system > const > eq_ref > ref > range > index > ALL
system/const:表中只有一行数据匹配,此时根据索引查询一次就能找到对应的数据
eq_ref:使用唯一索引扫描,常见于多表连接中使用主键和唯一索引作为关联条件
ref:非唯一索引扫描,还可见于唯一索引最左原则匹配扫描
range:索引范围扫描,比如,<,>,between 等操作
index:索引全表扫描,此时遍历整个索引树
ALL:表示全表扫描,需要遍历全表来找到对应的行
possible_keys:可能用到的索引
key:实际用到的索引
key_len:索引长度
ref:关联 id 等信息
rows:查找到记录所扫描的行数,SQL 优化重要指标,扫描的行数越少,性能越高
filtered:查找到所需记录占总扫描记录数的比例
Extra:额外的信息
explain select * from user u , biz_order b where u.id=b.user_id and u.id<20;
7、Show Profile 分析 SQL 执行性能
Show Profile 与 EXPLAIN 的区别是,前者主要是在外围分析;后者则是深入到 MySQL 内核,从执行线程的状态和时间来分析。
MySQL 是在 5.0.37 版本之后才支持 Show Profile ,select @@have_profiling
返回 YES
表示功能已开启。
mysql> show profiles;
Empty set, 1 warning (0.00 sec)
显示为空,说明profiles功能是关闭的。
通过下面命令开启
mysql> set profiling=1;
Query OK, 0 rows affected, 1 warning (0.00 sec)
获取 Query_ID
之后,通过 show profile for query ID
,查看 SQL 语句在执行过程中线程的每个状态所消耗的时间
完
往期推荐
100 行代码透彻解析 RPC 原理
北大数学天才“韦神”上热搜,随手帮6个博士解决困扰4个月的难题
各大框架都在使用的Unsafe类,到底有多神奇?
有道无术,术可成;有术无道,止于术
欢迎大家关注Java之道公众号
好文章,我在看❤️
阿里一面:SQL 优化有哪些技巧?相关推荐
- 复杂sql优化步骤与技巧
数据管理型系统,由于用户的要求或者系统设计要求,会出现大量表进行join,还要进行大量统计性数据查询展示,甚至数据权限控制等操作.最后会导致sql异常复杂,随着数据量增加,或者只是应用到生产环境(正式 ...
- sql优化建议与技巧
在sql查询中为了提高查询效率,我们常常会采取一些措施对查询语句进行sql优化,下面总结的一些方法,有需要的可以参考参考. 1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 ord ...
- JAVA代码优化,接口优化,SQL优化 (小技巧)
这里写目录标题
- SQL优化篇:如何成为一位写优质SQL语句的绝顶高手
(Structured Query Language)标准结构化查询语言简称SQL,编写SQL语句是每位后端开发日常职责中,接触最多的一项工作,SQL是关系型数据库诞生的产物,无论是什么数据库,MyS ...
- SQL优化篇:如何成为一位写优质SQL语句的绝顶高手!
写SQL语句不难,稍微系统学习过数据库相关技术的人都能做到,但想要写好SQL却也不是一件易事,在大多数编写SQL的时候,很多人都是以实现需求为原则去撰写的,当一条SQL写出来之后,只要能满足业务需求就 ...
- mysql问题定位_十、MySQL的SQL优化之定位SQL的问题 - 系统的撸一遍MySQL
找出SQL慢的原因 谈到MySQL不得不说的就是大家都会遇到的性能问题,今天就记录一下SQL优化相关的技巧. 检查MySQL状态 通过检查SQL语句的状态有助于MySQL的优化,首先介绍 show s ...
- 15 种 SQL 优化中,老司机才懂的处理技巧
前言 SQL优化是一个大家都比较关注的热门话题,无论你在面试,还是工作中,都很有可能会遇到. 如果某天你负责的某个线上接口,出现了性能问题,需要做优化.那么你首先想到的很有可能是优化SQL语句,因为它 ...
- 常用的7个SQl优化技巧
作为程序员经常和数据库打交道的时候还是非常频繁的,掌握住一些Sql的优化技巧还是非常有必要的.下面列出一些常用的SQl优化技巧,感兴趣的朋友可以了解一下. 1.注意通配符中Like的使用 以下写法会造 ...
- mysql 判断字段为null表示 false 其它为true_日拱一卒,MySQL数据库 常用SQL优化技巧 十一式...
本文中所提到的SQL优化技巧均是基于Mysql 索引 BTree类型 .将从以下几个方面介绍常用的SQL优化技巧: 避免在 WHERE 子句中使用 != 或 <> 操作符. 避免在 WHE ...
- sql优化技巧_使用这些查询优化技巧成为SQL向导
sql优化技巧 成为SQL向导! (Become an SQL Wizard!) It turns out storing data by rows and columns is convenient ...
最新文章
- R语言exists函数检查数据对象是否存在实战
- 图的遍历——广度优先搜索(Breadth First Search)
- oracle定时任务可以备份么,Linux下Oracle设置定时任务备份数据库的教程
- 深度学习为图片压缩算法赋能:节省55%带宽
- 理解MySQL——架构与概念
- 来自东软的 OpenStack 负载均衡即服务开源项目
- php7 php5.6 array,[转]php5.6 升级到php7及变化
- numpy ndarray可用的常规函数
- Linux 命令(133)—— groupdel 命令
- 诺基亚将于10月26日发布首款WindowsPhone7手机
- 推荐系统入门实践:世纪佳缘会员推荐
- 软件测试与软件开发比较?
- 更换计算机桌面背景的教案,《设置桌面背景》教学设计范文
- wireshark常用筛选命令
- HTML如何设置四边形,css实现三角形和平形四边形
- hadoop组件---面向列的开源数据库(九)--python--python使用thrift连接hbase
- 5.3 定积分的换元积分法和分部积分法
- 程序设计方法学-python
- MFC 加载jpg等图片
- [图文教程] 禁止 Windows 10 自动下载和更新驱动程序(转)
热门文章
- 医学图像预处理之CT成像原理
- 百练_3709:2进制转化为3进制
- Mybatis:高级知识1- resultMap实现一对一、一对多、多对多
- Android Design与Holo Theme详解
- 王道机考系列——数学问题
- 【EntityFramework CodeFirst 】错误解析:LINQ to Entities does not recognize the method ToString
- Bringing up interface eth0: Device eth0 does not seem to be present,delaying initialization
- 解决连接kudu时,delaying RPC due to Service unavailable: Master config (**.**.**.**:7051) has no leader
- 大数据监控大屏系统,有这些demo就足够了!
- c++ primer plus 第十四章 C++中的代码重用