【面试】你在项目中遇到过慢查询问题吗?你是怎么做SQL优化的?

news2025/1/15 13:14:21

文章目录

  • 前言
  • 一、找出有问题的SQL
    • 1、系统层面
    • 2、SQL语句层面
  • 二、查看SQL执行计划
  • 三、SQL优化案例
    • 慢查询
    • 优化步骤
  • SQL优化小结

前言

我在面试的时候很喜欢问候选人这样一个问题:“你在项目中遇到过慢查询问题吗?你是怎么做SQL优化的?”
很多时候,候选人会直接跟我说他们在编写SQL时会遵循的一些常用技巧,比如:

  • 合理使用索引
  • 使用UNION ALL替代UNION
  • 不要使用select * 写法
  • JOIN字段建议建立索引
  • 避免复杂SQL语句

这里不能说完全错误,因为这些技巧确实可以提高SQL运行效率;
但是也不能说完全正确,毕竟我是想问他具体怎么是做SQL优化的。

接下来我问他,我这里有一段复杂的SQL,你可以动手帮我优化一下吗?
到这一步的时候就有很多候选人做不好打了退堂鼓。他们有很扎实的理论知识,但是动手能力却差点火候。

今天这篇文章就从实战的角度出发,带大家走一遍SQL优化的真实流程。

一、找出有问题的SQL

在实际开发中要判断一段SQL有没有问题可以从两方面来判断:

1、系统层面

  • CPU消耗严重
  • IO等待严重
  • 页面响应时间过长
  • 应用的日志出现超时等错误

2、SQL语句层面

  • 冗长
  • 执行时间过长
  • 从全表扫描获取数据
  • 执行计划中的rows、cost很大

冗长的SQL都好理解,一段SQL太长阅读性肯定会差,出现问题的频率肯定会更高。更进一步判断SQL问题就必须得从执行计划入手,如下所示:
在这里插入图片描述

执行计划告诉我们本次查询走了全表扫描Type=ALL,rows很大(9950400)基本可以判断这是一段"有味道"的SQL。

二、查看SQL执行计划

找到了有问题的SQL就要确定优化方案,那究竟从何处下手呢?这里必须要通过执行计划来观察。
执行计划会告诉你哪些地方效率低,哪里可以需要优化。我们以MYSQL为例,看看执行计划是什么。(每个数据库的执行计划都不一样,需要自行了解)

explain select * from xxx

当使用explain sql后会看到执行计划
在这里插入图片描述

执行计划中几个重要字段的解释说明,大家需要记住

字段解释
id每个被独立执行的操作标识,标识对象被操作的顺序,id值越大,先被执行,如果相同,执行顺序从上到下
select_type查询中每个select 字句的类型
table被操作的对象名称,通常是表名,但有其他格式
partitions匹配的分区信息(对于非分区表值为NULL)
type连接操作的类型
possible_keys可能用到的索引
key优化器实际使用的索引(最重要的列) 从最好到最差的连接类型为const、eq_reg、ref、range、index和ALL。当出现ALL时表示当前SQL出现了“坏味道”
key_len被优化器选定的索引键长度,单位是字节
ref表示本行被操作对象的参照对象,无参照对象为NULL
rows查询执行所扫描的元组个数(对于innodb,此值为估计值)
filtered条件表上数据被过滤的元组个数百分比
extra执行计划的重要补充信息,当此列出现Using filesort , Using temporary 字样时就要小心了,很可能SQL语句需要优化

通过执行计划我们就可以确定优化方案,优化一处后再回过头来观察执行计划,如此往复循环直到找到最优目标为止。

下面给出一段有问题的SQL具体操作一下。

三、SQL优化案例

慢查询

1、表结构如下:

CREATE TABLE `a`
(
    `id`          int(11) NOT NULLAUTO_INCREMENT,
    `seller_id`   bigint(20)                                       DEFAULT NULL,
    `seller_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
    `gmt_create`  varchar(30)                                      DEFAULT NULL,
    PRIMARY KEY (`id`)
);
CREATE TABLE `b`
(
    `id`          int(11) NOT NULLAUTO_INCREMENT,
    `seller_name` varchar(100) DEFAULT NULL,
    `user_id`     varchar(50)  DEFAULT NULL,
    `user_name`   varchar(100) DEFAULT NULL,
    `sales`       bigint(20)   DEFAULT NULL,
    `gmt_create`  varchar(30)  DEFAULT NULL,
    PRIMARY KEY (`id`)
);
CREATE TABLE `c`
(
    `id`         int(11) NOT NULLAUTO_INCREMENT,
    `user_id`    varchar(50)  DEFAULT NULL,
    `order_id`   varchar(100) DEFAULT NULL,
    `state`      bigint(20)   DEFAULT NULL,
    `gmt_create` varchar(30)  DEFAULT NULL,
    PRIMARY KEY (`id`)
);

2、有问题的查询SQL

select a.seller_id,
       a.seller_name,
       b.user_name,
       c.state
from a,
     b,
     c
where a.seller_name = b.seller_name
  and b.user_id = c.user_id
  and c.user_id = 17
  and a.gmt_create
    BETWEEN DATE_ADD(NOW(), INTERVAL600 MINUTE)
    AND DATE_ADD(NOW(), INTERVAL 600 MINUTE)
order by a.gmt_create;

a,b,c 三张表关联,查询用户17 在当前时间前后10个小时的订单情况,并根据订单创建时间升序排列

优化步骤

1、先查看各表数据量
在这里插入图片描述

2、查看原执行时间,总耗时0.21s
在这里插入图片描述

3、查看原执行计划
在这里插入图片描述

4、通过观察执行计划和SQL语句,确定初步优化方案

  • SQL中 where条件字段类型要跟表结构一致,表中 user_id 为varchar(50)类型,实际SQL用的int类型,存在隐式转换,也未添加索引。将b和c表 user_id 字段改成int类型。
  • 因存在b表和c表关联,将b和c表 user_id创建索引
  • 因存在a表和b表关联,将a和b表 seller_name字段创建索引
  • 利用复合索引消除临时表和排序

初步优化的SQL:

alter table b modify `user_id` int(10) DEFAULT NULL;
alter table c modify `user_id` int(10) DEFAULT NULL;
alter table c add index `idx_user_id`(`user_id`);
alter table b add index `idx_user_id_sell_name`(`user_id`,`seller_name`);
alter table a add index `idx_sellname_gmt_sellid`(`gmt_create`,`seller_name`,`seller_id`);

查看优化后的执行时间
在这里插入图片描述

初步优化后执行速度提升了20倍,是否还能继续优化呢?
5、继续查看优化后的执行计划
在这里插入图片描述

这里只看到查询需要扫描的元素比较大,不过还看到了有两处告警信息,直接查看告警信息

show warnings

Cannot use range access on index ‘idx_sellname_gmt_sellid’ due to type or collation conversion on field ‘get_create’,这句话是告诉你由于gmt_create列发生了类型转换所以无法走索引。
查看SQL建表语句发现gmt_create字段被设计成了varchar类型,在SQL查询时需要转化成时间格式做查询,确实不能走索引。
所以需要调整一下gmt_create字段格式

alter table a modify "gmt_create" datetime DEFAULT NULL;

6、修改字段后再来查看执行时间
在这里插入图片描述

执行速度非常完美。
7、再观察优化后的执行计划
在这里插入图片描述

可以看到执行计划也很完美,至此SQL优化结束。

SQL优化小结

这里给大家总结一下优化SQL的套路

  • 查看执行计划 explain
  • 如果有告警信息,查看告警信息 show warnings;
  • 查看SQL涉及的表结构和索引信息
  • 根据执行计划,思考可能的优化点
  • 按照可能的优化点执行表结构变更、增加索引、SQL改写等操作
  • 查看优化后的执行时间和执行计划
  • 如果优化效果不明显,重复第四步操作

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/435749.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

含分布式电源的配电网可靠性评估研究(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

Windows服务搭建web网站,使用cpolar内网穿透实现公网访问

文章目录 概述1. 搭建一个静态Web站点2. 本地浏览测试站点是否正常3. 本地站点发布公网可访问3.1 安装cpolar内网穿透3.2 创建隧道映射公网地址3.3 获取公网URL地址 4. 公网远程访问内网web站点5. 配置固定二级子域名5.1 保留二级子域名5.2 配置二级子域名 6. 测试访问二级子域…

Activiti7 工作流非原流程终止

背景 正常工作流,需要经过 node1、node2 才能结束。 现在要求已经开启的流程,目前停留在 node1,可以提前终止。 方案 一般根据实际需要,可以有几种做法: 新绘制流程图,新增 node1 结束的流程分支&#x…

基于 JESD204B 协议ARM+FPGA+AD多板卡多通道同步采集实现方法

0 引言 随着数字化信号处理技术的不断进步,对数字信号 的处理已经成为当前大多数工程应用的基本方法。由于 模拟信号才是现实生活中的原始信号,为了工程研究实 现的可能,需将模拟信号转换为数字信号才能在工程中 处理,AD 转换…

独立按键控制LED移位

1.这就是LED移位的原理 2. #include <REGX52.H> void Delay(unsigned int xms);unsigned char LEDNum;//LEDNum为0000 0000void main() {P2~0x01; //上电默认LED1点亮while(1){if(P3_10) //如果K1按键按下&#xff0c;LED灯往右依次亮起{Delay(20);while(P3_10);//消…

Bandizip已管理员身份运行

系列文章目录 文章目录 系列文章目录前言一、Bandzib是什么&#xff1f;二、使用步骤1.引入库 前言 在解压krita源码包时Bandizip报错 一、Bandzib是什么&#xff1f; bandzip官网 Bandizip 是一款压缩软件&#xff0c;它支持Zip、7-Zip 和 RAR 以及其它压缩格式。它拥有非…

【22岁,想转行IT,请问培训出来真的能找到工作吗?】

首先需要肯定的是&#xff0c;22岁是一个转行IT的好时间&#xff0c;大概猜想你是大学应届生吧&#xff0c;学历和年龄都是IT企业们非常喜欢的&#xff0c;这个时候如果你刚好有一身过硬的专业技能&#xff0c;那就非常完美了。那么你现在想转行学习&#xff0c;目前对于IT行业…

SpringBoot 整合 ChatGPT API 项目实战

SpringBoot 整合 ChatGPT API 项目实战 一、准备工作 二、补全接口示例 三、申请API-KEY 四、JavaScript调用API 五、SpringBoot使用ChatGPT API 体验到了ChatGPT的强大之后&#xff0c;那么我们会想&#xff0c;如果我们想基于ChatGPT开发一个自己的聊天机器人&#xff0…

计算机网络复习记录(总结 —— 快速入门和快速复习)

一、计算机网络的定义和分类 定义&#xff1a; 简单定义&#xff1a;一些互连、自治、的计算机集合。 较好定义&#xff1a;计算机网络主要是由一些通用的、可编程的硬件互连而成&#xff0c;而这些硬件并非专门用来实现某一特定目的。 分类 按交换技术分类 按使用者分类 …

【工作思考】如何提升自己的编程能力?

文章目录 前言一、代码评审为什么要进行代码评审&#xff1f; 二、持续学习能力三、良好的编程习惯代码注释避免深度嵌套拒绝长函数重视自测文档编写重构你的代码学会思考 四、多接触开源项目五、总结 前言 在工作中&#xff0c;我们大部分的时间都是在阅读代码&#xff0c;阅…

CF204A-Little Elephant and Interval(数位)

CF204A-Little Elephant and Interval 考虑 [ 1 , a b c d e ‾ ] [1,\overline{abcde}] [1,abcde] 的情况&#xff1a; 位置集合数量个位1 ~ 99十位11 ~ 999百位 { x u x ‾ ∣ x ∈ [ 1 , 9 ] , u ∈ [ 0 , 9 ] } \{\overline{xux} | x\in [1,9],u\in [0,9]\} {xux∣x∈[1…

基于Yolov5的二维码QR码识别

1.QR code介绍 一个 QR 码可以分为两个部分&#xff1a;功能图形和编码区域。 数据集 大小10,85张 1.1 通过split_train_val.py得到trainval.txt、val.txt、test.txt # coding:utf-8import os import random import argparseparser argparse.ArgumentParser() #xml文件的地…

设计模式-结构型模式之代理模式

6. 代理模式 6.1. 模式动机 在某些情况下&#xff0c;一个客户不想或者不能直接引用一个对 象&#xff0c;此时可以通过一个称之为“代理”的第三者来实现 间接引用。代理对象可以在客户端和目标对象之间起到 中介的作用&#xff0c;并且可以通过代理对象去掉客户不能看到 的内…

江苏专转本盐城工学院管理学章节习题

江苏专转本盐城工学院管理学章节习题第一章 管理活动与管理理论 一、单项选择题 1.企业在销售产品时,需要预估货款回收的可能性。为此&#xff0c;信用审核部门力图以一种低成本的方式处理有关客户资信的材料,但因为过程速度太慢,使许多客户另求他处购货。该项信用审核工作可…

Power Automate实现自动填充Word

创建Word模板 1、创建一个Word&#xff0c;按需求写好内容 2、在需要填充的地方插入开发工具-纯文本内容控件 3、编辑控件属性&#xff0c;用于Power Automate中区分字段 4、模板完成后上传至Sharepoint站点中 创建Forms 也可使用Sharepoint列表作申请单&#xff0c;这步就…

实战:快速实现iOS应用中集成即时通讯IM和UI

准备 熟练objective-c语言 有一台mac电脑,并安装了xcode 和 cocoapods 目标 手把手教大家在iOS应用中集成即时通讯IM 功能 内容篇幅较长,需要内心平和耐心看下去,务必戒躁.阅读本文并按照本文进行对接预计时长2小时 注册Appkey和username 本教程以集成环信IM为例 注册环信…

SpringBoot 整合 ES (四十二)

我看到希望&#xff0c;哪怕只有微小的一束光&#xff0c;我也会拼尽全力去寻找 上一章简单介绍了 SpringBoot 整合 RabbitMQ (四十一), 如果没有看过,请观看上一章 ES 相应的教程&#xff0c;可以看老蝴蝶之前写的文章: https://blog.csdn.net/yjltx1234csdn/category_122775…

Java 基础常识

一、Java运行机制 1.Java运行原理 编译&#xff1a;.java(源代码) ---> .class(字节码) 解释&#xff1a;.class(字节码) ---> 加载并启动JVM(类加载) ---> .class(机器指令) 执行&#xff1a;通过JVM来完成运行输出 2.Java运行过程 利用 javac 编译 .java 文件 利…

欧姆龙CP1H系列PLC通讯扩展与数据采集

一、应用场景 纺织厂的粗纱机&#xff0c;控制系统由1台欧姆龙CP1H的PLC和1台昆仑通泰MCGS的触摸屏组成&#xff0c;触摸屏连接到PLC通讯扩展的接口CP1W-CIF01&#xff08;RS232串行通讯&#xff09;。现在MES管理系统&#xff0c;需要采集设备的数据&#xff0c;要求不改变原来…

【详解C++中的引用】

文章目录 一、什么是引用二、引用规则三、引用特性四、使用场景1.做函数参数2.做返回值五、常引用 ps&#xff1a;为什么类型转换会产生临时变量&#xff1f; 六、引用和指针的区别总结 一、什么是引用 引用就是给一个变量取别名。 注意&#xff1a;这个引用不会新开辟一块空…