百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程网 > 正文

阿里一面:SQL 优化有哪些技巧?

yuyutoo 2025-02-10 14:58 2 浏览 0 评论

原文公众号:微观技术

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 语句在执行过程中线程的每个状态所消耗的时间




相关推荐

史上最全的浏览器兼容性问题和解决方案

微信ID:WEB_wysj(点击关注)◎◎◎◎◎◎◎◎◎一┳═┻︻▄(页底留言开放,欢迎来吐槽)●●●...

平面设计基础知识_平面设计基础知识实验收获与总结
平面设计基础知识_平面设计基础知识实验收获与总结

CSS构造颜色,背景与图像1.使用span更好的控制文本中局部区域的文本:文本;2.使用display属性提供区块转变:display:inline(是内联的...

2025-02-21 16:01 yuyutoo

写作排版简单三步就行-工具篇_作文排版模板

和我们工作中日常word排版内部交流不同,这篇教程介绍的写作排版主要是用于“微信公众号、头条号”网络展示。写作展现的是我的思考,排版是让写作在网格上更好地展现。在写作上花费时间是有累积复利优势的,在排...

写一个2048的游戏_2048小游戏功能实现

1.创建HTML文件1.打开一个文本编辑器,例如Notepad++、SublimeText、VisualStudioCode等。2.将以下HTML代码复制并粘贴到文本编辑器中:html...

今天你穿“短袖”了吗?青岛最高23℃!接下来几天气温更刺激……

  最近的天气暖和得让很多小伙伴们喊“热”!!!  昨天的气温到底升得有多高呢?你家有没有榜上有名?...

CSS不规则卡片,纯CSS制作优惠券样式,CSS实现锯齿样式

之前也有写过CSS优惠券样式《CSS3径向渐变实现优惠券波浪造型》,这次再来温习一遍,并且将更为详细的讲解,从布局到具体样式说明,最后定义CSS变量,自定义主题颜色。布局...

柠檬科技肖勃飞:大数据风控助力信用社会建设

...

你的自我界限够强大吗?_你的自我界限够强大吗英文

我的结果:A、该设立新的界限...

行内元素与块级元素,以及区别_行内元素和块级元素有什么区别?

行内元素与块级元素首先,CSS规范规定,每个元素都有display属性,确定该元素的类型,每个元素都有默认的display值,分别为块级(block)、行内(inline)。块级元素:(以下列举比较常...

让“成都速度”跑得潇潇洒洒,地上地下共享轨交繁华
让“成都速度”跑得潇潇洒洒,地上地下共享轨交繁华

去年的两会期间,习近平总书记在参加人大会议四川代表团审议时,对治蜀兴川提出了明确要求,指明了前行方向,并带来了“祝四川人民的生活越来越安逸”的美好祝福。又是一年...

2025-02-21 16:00 yuyutoo

今年国家综合性消防救援队伍计划招录消防员15000名

记者24日从应急管理部获悉,国家综合性消防救援队伍2023年消防员招录工作已正式启动。今年共计划招录消防员15000名,其中高校应届毕业生5000名、退役士兵5000名、社会青年5000名。本次招录的...

一起盘点最新 Chrome v133 的5大主流特性 ?

1.CSS的高级attr()方法CSSattr()函数是CSSLevel5中用于检索DOM元素的属性值并将其用于CSS属性值,类似于var()函数替换自定义属性值的方式。...

竞走团体世锦赛5月太仓举行 世界冠军杨家玉担任形象大使

style="text-align:center;"data-mce-style="text-align:...

学物理能做什么?_学物理能做什么 卢昌海

作者:曹则贤中国科学院物理研究所原标题:《物理学:ASourceofPowerforMan》在2006年中央电视台《对话》栏目的某期节目中,主持人问过我一个的问题:“学物理的人,如果日后不...

你不知道的关于这只眯眼兔的6个小秘密
你不知道的关于这只眯眼兔的6个小秘密

在你们忙着给熊本君做表情包的时候,要知道,最先在网络上引起轰动的可是这只脸上只有两条缝的兔子——兔斯基。今年,它更是迎来了自己的10岁生日。①关于德艺双馨“老艺...

2025-02-21 16:00 yuyutoo

取消回复欢迎 发表评论: