腾讯面试题:一条SQL语句执行得很慢的原因有哪些?

实体对齐(Entity Alignment)相关论文与数据集整理 实体对齐(Entity Alignment)、知识图谱融合方法总结整理 年份 模型 主要思想 博文推荐 论文 代码 2019 Entity Alignment between Knowledge Graphs Using Attribute Embeddings 实体对齐数据集整理 名称 — DBpe-dia(DBP) LinkedGeoData(LGD) Geonames(GEO) YAGO ... 阅读详情

最近的招聘季,腾讯有一道面试题:一条SQL语句执行得很慢的原因有哪些?

其实,这个问题可以涉及到 MySQL 的很多核心知识,可以扯出一大堆,就像要考你计算机网络的知识时,问你“输入URL回车之后,究竟发生了什么”一样,看看你能说出多少了。

本文的作者就是这道面试题的亲历者,他尝试总结了一下:

一、开始装逼:分类讨论

一条 SQL 语句执行的很慢,那是每次执行都很慢呢?还是大多数情况下是正常的,偶尔出现很慢呢?所以我觉得,我们还得分以下两种情况来讨论。

1、大多数情况是正常的,只是偶尔会出现很慢的情况。

2、在数据量不变的情况下,这条SQL语句一直以来都执行的很慢。

针对这两种情况,我们来分析下可能是哪些原因导致的。

二、针对偶尔很慢的情况

一条 SQL 大多数情况正常,偶尔才能出现很慢的情况,针对这种情况,我觉得这条SQL语句的书写本身是没什么问题的,而是其他原因导致的,那会是什么原因呢?

1、数据库在刷新脏页(flush)我也无奈啊

当我们要往数据库插入一条数据、或者要更新一条数据的时候,我们知道数据库会在内存中把对应字段的数据更新了,但是更新之后,这些更新的字段并不会马上同步持久化到磁盘中去,而是把这些更新的记录写入到 redo log 日记中去,等到空闲的时候,在通过 redo log 里的日记把最新的数据同步到磁盘中去。

当内存数据页跟磁盘数据页内容不一致的时候,我们称这个内存页为“脏页”。内存数据写入到磁盘后,内存和磁盘上的数据页的内容就一致了,称为“干净页”。

刷脏页有下面4种场景(后两种不用太关注“性能”问题):

  • redolog写满了:redo log 里的容量是有限的,如果数据库一直很忙,更新又很频繁,这个时候 redo log 很快就会被写满了,这个时候就没办法等到空闲的时候再把数据同步到磁盘的,只能暂停其他操作,全身心来把数据同步到磁盘中去的,而这个时候,就会导致我们平时正常的SQL语句突然执行的很慢,所以说,数据库在在同步数据到磁盘的时候,就有可能导致我们的SQL语句执行的很慢了。

  • 内存不够用了:如果一次查询较多的数据,恰好碰到所查数据页不在内存中时,需要申请内存,而此时恰好内存不足的时候就需要淘汰一部分内存数据页,如果是干净页,就直接释放,如果恰好是脏页就需要刷脏页。

  • MySQL 认为系统“空闲”的时候:这时系统没什么压力。

  • MySQL 正常关闭的时候:这时候,MySQL 会把内存的脏页都 flush 到磁盘上,这样下次 MySQL 启动的时候,就可以直接从磁盘上读数据,启动速度会很快。

2、拿不到锁我能怎么办

这个就比较容易想到了,我们要执行的这条语句,刚好这条语句涉及到的,别人在用,并且加锁了,我们拿不到锁,只能慢慢等待别人释放锁了。或者,表没有加锁,但要使用到的某个一行被加锁了,这个时候,我也没办法啊。

如果要判断是否真的在等待锁,我们可以用show processlist这个命令来查看当前的状态哦,这里我要提醒一下,有些命令最好记录一下,反正,我被问了好几个命令,都不知道怎么写,呵呵。

下来我们来访分析下第二种情况,我觉得第二种情况的分析才是最重要的

三、针对一直都这么慢的情况

如果在数据量一样大的情况下,这条 SQL 语句每次都执行的这么慢,那就就要好好考虑下你的 SQL 书写了,下面我们来分析下哪些原因会导致我们的 SQL 语句执行的很不理想。

我们先来假设我们有一个表,表里有下面两个字段,分别是主键 id,和两个普通字段 c 和 d。

mysql> CREATE TABLE `t` (
  `id` int(11) NOT NULL,
  `c` int(11) DEFAULT NULL,
  `d` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;

1、扎心了,没用到索引

没有用上索引,我觉得这个原因是很多人都能想到的,例如你要查询这条语句

select * from t where 100 <c and c < 100000;

(1)、字段没有索引

刚好你的 c 字段上没有索引,那么抱歉,只能走全表扫描了,你就体验不会索引带来的乐趣了,所以,这回导致这条查询语句很慢。

(2)、字段有索引,但却没有用索引

好吧,这个时候你给 c 这个字段加上了索引,然后又查询了一条语句

select * from t where c - 1 = 1000;

我想问大家一个问题,这样子在查询的时候会用索引查询吗?

答是不会,如果我们在字段的左边做了运算,那么很抱歉,在查询的时候,就不会用上索引了,所以呢,大家要注意这种字段上有索引,但由于自己的疏忽,导致系统没有使用索引的情况了。

正确的查询应该如下

select * from t where c = 1000 + 1;

有人可能会说,右边有运算就能用上索引?难道数据库就不会自动帮我们优化一下,自动把 c - 1=1000 自动转换为 c = 1000+1。

不好意思,确实不会帮你,所以,你要注意了。

(3)、函数操作导致没有用上索引

如果我们在查询的时候,对字段进行了函数操作,也是会导致没有用上索引的,例如

select * from t where pow(c,2) = 1000;

这里我只是做一个例子,假设函数 pow 是求 c 的 n 次方,实际上可能并没有 pow(c,2)这个函数。其实这个和上面在左边做运算也是很类似的。

所以呢,一条语句执行都很慢的时候,可能是该语句没有用上索引了,不过具体是啥原因导致没有用上索引的呢,你就要会分析了,我上面列举的三个原因,应该是出现的比较多的吧。

2、呵呵,数据库自己选错索引了

我们在进行查询操作的时候,例如

select * from t where 100 < c and c < 100000;

我们知道,主键索引和非主键索引是有区别的,主键索引存放的值是整行字段的数据,而非主键索引上存放的值不是整行字段的数据,而且存放主键字段的值

也就是说,我们如果走 c 这个字段的索引的话,最后会查询到对应主键的值,然后,再根据主键的值走主键索引,查询到整行数据返回。

好吧扯了这么多,其实我就是想告诉你,就算你在 c 字段上有索引,系统也并不一定会走 c 这个字段上的索引,而是有可能会直接扫描扫描全表,找出所有符合 100 < c and c < 100000 的数据。

为什么会这样呢?

其实是这样的,系统在执行这条语句的时候,会进行预测:究竟是走 c 索引扫描的行数少,还是直接扫描全表扫描的行数少呢?显然,扫描行数越少当然越好了,因为扫描行数越少,意味着I/O操作的次数越少。

如果是扫描全表的话,那么扫描的次数就是这个表的总行数了,假设为 n;而如果走索引 c 的话,我们通过索引 c 找到主键之后,还得再通过主键索引来找我们整行的数据,也就是说,需要走两次索引。而且,我们也不知道符合 100 c < and c < 10000 这个条件的数据有多少行,万一这个表是全部数据都符合呢?这个时候意味着,走 c 索引不仅扫描的行数是 n,同时还得每行数据走两次索引。

所以呢,系统是有可能走全表扫描而不走索引的。那系统是怎么判断呢?

判断来源于系统的预测,也就是说,如果要走 c 字段索引的话,系统会预测走 c 字段索引大概需要扫描多少行。如果预测到要扫描的行数很多,它可能就不走索引而直接扫描全表了。

那么问题来了,系统是怎么预测判断的呢?这里我给你讲下系统是怎么判断的吧,虽然这个时候我已经写到脖子有点酸了。

系统是通过索引的区分度来判断的,一个索引上不同的值越多,意味着出现相同数值的索引越少,意味着索引的区分度越高。我们也把区分度称之为基数,即区分度越高,基数越大。所以呢,基数越大,意味着符合 100 < c and c < 10000 这个条件的行数越少。

所以呢,一个索引的基数越大,意味着走索引查询越有优势。

那么问题来了,怎么知道这个索引的基数呢?

系统当然是不会遍历全部来获得一个索引的基数的,代价太大了,索引系统是通过遍历部分数据,也就是通过采样的方式,来预测索引的基数的。

扯了这么多,重点的来了,居然是采样,那就有可能出现失误的情况,也就是说,c 这个索引的基数实际上是很大的,但是采样的时候,却很不幸,把这个索引的基数预测成很小。例如你采样的那一部分数据刚好基数很小,然后就误以为索引的基数很小。然后就呵呵,系统就不走 c 索引了,直接走全部扫描了

所以呢,说了这么多,得出结论:由于统计的失误,导致系统没有走索引,而是走了全表扫描,而这,也是导致我们 SQL 语句执行的很慢的原因。

这里我声明一下,系统判断是否走索引,扫描行数的预测其实只是原因之一,这条查询语句是否需要使用使用临时表、是否需要排序等也是会影响系统的选择的。

不过呢,我们有时候也可以通过强制走索引的方式来查询,例如

select * from t force index(a) where c < 100 and c < 100000;

我们也可以通过

show index from t;

来查询索引的基数和实际是否符合,如果和实际很不符合的话,我们可以重新来统计索引的基数,可以用这条命令

analyze table t;

来重新统计分析。

既然会预测错索引的基数,这也意味着,当我们的查询语句有多个索引的时候,系统有可能也会选错索引哦,这也可能是 SQL 执行的很慢的一个原因。

好吧,就先扯这么多了,你到时候能扯出这么多,我觉得已经很棒了,下面做一个总结。

四、总结

以上是我的总结与理解,最后一个部分,我怕很多人不大懂数据库居然会选错索引,所以我详细解释了一下,下面我对以上做一个总结。

一个 SQL 执行的很慢,我们要分两种情况讨论:

1、大多数情况下很正常,偶尔很慢,则有如下原因

(1)、数据库在刷新脏页,例如 redo log 写满了需要同步到磁盘。

(2)、执行的时候,遇到锁,如表锁、行锁。

2、这条 SQL 语句一直执行的很慢,则有如下原因。

(1)、没有用上索引:例如该字段没有索引;由于对字段进行运算、函数操作导致无法用索引。

(2)、数据库选错了索引。

大家如果有补充的,也是可以留言区补充一波哦。

 

更多面试答案以及面试技巧

限于篇幅的原因各位需要资料的小伙伴可以加我Q群809389099免费获取

10ä¸ªææ¶å¥40ä¸ï¼æ¥äº30å¤ä¸ªåå­ï¼é¿éåå·¥æ³è¾è

资料领取方式:关注+点赞后加入我的Q群即可免费获取!

POVME3口袋体积计算:从.ini配置到实战解析 本文详细解析了POVME3口袋体积计算工具,从核心原理、环境准备到实战应用。重点剖析了控制计算行为的.ini配置文件,包括如何定义口袋区域、精修范围及锁定目标,并提供了固定坐标与配体引导两种实战策略,帮助研究人员从分子动力学轨迹中量化分析蛋白质结合口袋的动态变化。 阅读详情

相关推荐

【MySQL数据库】一条SQL语句为什么执行这么

面试高频题目,一条SQL语句为什么执行这么? 这其中涉及的知识也是各种各样,今天就让我们来完全剖析这个问题。 一条SQL语句为什么执行这么?一、执行偶尔变1. 刷脏页,写磁盘2. 还在等锁3. 回滚日志过多二、执行总是很慢1. 没有索引2. 对字段进行函数操作3. 选错索引 一、执行偶尔变 有的时候,明明执行的是同一条语句,之前执行还挺快的,但忽然某一次就像“卡住了一样”需要很久才能返回结果,甚至是长时间不返回。出现这种情况呢,就需要考虑以下两种情况: 1. 刷脏页,写磁盘 首先说明脏页的概念:当内存数据页跟磁盘数据页内容不一致的时候,我们称这个内存页为“脏页”。内存数据写入到磁盘后,

一条SQL语句执行很慢原因有哪些?(转)

一条SQL语句执行很慢,那是每次执行很慢呢?还是大多数情况下是正常的,偶尔出现很慢呢?所以我觉得,我们还得分以下两种情况来讨论。 1、大多数情况是正常的,只是偶尔会出现很慢的情况。 2、在数据量不变的情况下,这条SQL语句一直以来都执行很慢。 针对这两种情况,我们来分析下可能是哪些原因导致的。 二、针对偶尔很慢的情况 一条SQL大多数情况正常,偶尔才能出现很慢的情况,针对这...

weixin_33961829的博客 1203

2020年上海市全域建筑面矢量数据包(含城乡建筑轮廓、建筑面积与常住人口字段)

这套数据覆盖2020年上海全市范围,包含城区和农村所有建筑物的面状矢量边界,每个建筑面要素均附带建筑面积(平方米)和对应常住人口数量两个关键属性字段。数据以标准Shapefile格式组织,包含.shp、.shx、.dbf、.prj、.cpg和.xml六个必要文件,可直接加载进ArcGIS、QGIS等GIS平台进行空间分析或导入SWMM等城市水文模型中作为下垫面基础图层。适用于城市内涝模拟中的不透水面划分、建筑能源消耗估算、人口空间分布建模、城乡发展对比分析以及精细化城市规划底图构建等实际业务场景。文件结构完整,坐标系为WGS84地理坐标系(EPSG:4326),属性表字段命名清晰,无缺失值,开箱即用。

使用mybatis执行sql语句很慢,但是把sql提出来到终端执行很快

问题现象:在进行接口性能测试时,发现一个查询详情的接口反应速度在10s左右,日志打印定位到一条sql执行执行很慢,于是将sql复制到终端执行执行速度100ms左右。 使用数据库:pgsql数据量100w 示例代码:select * from table_a a join table_b b on a.project_no = b.project_no and a.id = #{id} 解决方案:①将#替换为$,使用此方法可能导致sql注入

m0_70239336的博客 4078

Mybatis实现批量更新数据,提高程序更新语句性能

sql批量更新 实际实践(传入的是List<Map<String, Object>>) 1) SQL方法 void updateBatchGuardsLevelMpPicsBatch(@Param("levelPics") List<GuardsLevelMpPic> levelPics); 2) SQL语句 务必注意:一定要加where条件,里面的id为需要更新的数据的id;如果不加where条件,则会全部更新,但是需要更新且有数据的更新为传递的数据

cwwlzm的博客 1449

mybatis批量更新数据三种方法效率对比

探讨批量更新数据三种写法的效率问题。 实现方式有三种, 一种用for循环通过循环传过来的参数集合,循环出N条sql, 另一种 用mysql的case when 条件判断变相的进行批量更新 还有一个是用ON DUPLICATE KEY UPDATE进行批量更新 下面进行实现。 注意第一种方法要想成功,需要在db链接url后面带一个参数 &allowMultiQueries=true 即: jdbc:mysql://localhost:3306/mysqlTest?characte...

清水的专栏 1520

关于sql数据执行很快,在mybatis执行很慢的问题

如标题所述,最近碰到了这个问题,一般出现这种问题,一个特征就是sql写的很长,而且很多if标签和占位符#{}。 1、用到的where条件字段存在隐式转换 举个例子,sql有个时间字段,数据库是date类型,java实体里是util.date类型,这样的话,mybatis会把实体的时间字段转为timestamp类型,导致你的时间字段用不到索引,这样就走了错误的执行计划。解决办法就是字段类型统一。 2、数据倾斜(skew data)的列上用到占位符 这里牵扯到了变量窥探的东西,Oracle在处理带有绑定

qq_38392542的博客 1万+

【超详细总结】腾讯面试题一条 sql 语句执行很慢原因有哪些?

说实话,这个问题可以涉及到 MySQL 的很多核心知识,可以扯出一大堆,就像要考你计算机网络的知识时,问你“输入URL回车之后,究竟发生了什么”一样,看看你能说出多少了。 之前腾讯面试的实话,也问到这个问题了,不过答的很不好,之前没去想过相关原因,导致一时之间扯不出来。所以今天,我带大家来详细扯一下有哪些原因,相信你看完之后一定会有所收获,不然你打我。 开始装逼:分类讨论 一条 SQL 语句执行的...

帅地 1万+

腾讯面试题:一条SQL语句执行很慢原因有哪些?

这个问题可以涉及到 MySQL 的很多核心知识,可以扯出一大堆,就像要考你计算机网络的知识时,问你“输入URL回车之后,究竟发生了什么”一样,看看你能说出多少了。 1. 分析问题 大多数情况是正常的,知识偶尔的时候会出现很慢的情况。 在数据量不变的情况下,这条SQL语句一直以来都执行很慢 2. 数据库在刷新脏页我也无奈啊 一条SQL语句执行速度一般情...

SmallCatBaby的博客 361

怎么用sql语句_腾讯面试题一条 SQL 语句执行很慢原因有哪些?

(给ImportNew加星标,提高Java技能)转自:苦逼的码农最近的招聘季,腾讯有一道面试题一条SQL语句执行很慢原因有哪些?其实,这个问题可以涉及到 MySQL 的很多核心知识,可以扯出一大堆,就像要考你计算机网络的知识时,问你“输入URL回车之后,究竟发生了什么”一样,看看你能说出多少了。本文的作者就是这道面试题的亲历者,他尝试总结了一下:一、开始装逼:分类讨论一条 SQL ...

weixin_39719732的博客 93

【转】腾讯面试题一条 SQL 语句执行很慢原因有哪些?

【转】腾讯面试题一条 SQL 语句执行很慢原因有哪些? 转自文章链接:https://mp.weixin.qq.com/s/bAzEsUQBi02Tfuo-n0k_lA 帅地 [ImportNew](javascript:void(0)

一直很安静 282

淘汰 sql_腾讯面试题一条SQL语句执行很慢原因有哪些?

本文转载自微信公众号:苦逼的码农最近的招聘季,腾讯有一道面试题一条SQL语句执行很慢原因有哪些?其实,这个问题可以涉及到MySQL的很多核心知识,可以扯出一大堆,就像要考你计算机网络的知识时,问你“输入URL回车之后,究竟发生了什么”一样,看看你能说出多少了。本文的作者就是这道面试题的亲历者,他尝试总结了一下:一、开始装逼:分类讨论一条SQL语句执行很慢,那是每次执行都很...

weixin_30894765的博客 72

本地执行快 服务器执行_腾讯面试题一条 SQL 语句执行很慢原因有哪些?...

(给ImportNew加星标,提高Java技能)转自:苦逼的码农最近的招聘季,腾讯有一道面试题一条SQL语句执行很慢原因有哪些?其实,这个问题可以涉及到 MySQL 的很多核心知识,可以扯出一大堆,就像要考你计算机网络的知识时,问你“输入URL回车之后,究竟发生了什么”一样,看看你能说出多少了。本文的作者就是这道面试题的亲历者,他尝试总结了一下:一、开始装逼:分类讨论一条 SQL ...

weixin_39795479的博客 1287

本机mysql数据库引擎是innob_但是sql语句执行还是很慢_腾讯面试题一条SQL语句执行很慢原因有哪些?...

本文转载自微信公众号:苦逼的码农最近的招聘季,腾讯有一道面试题一条SQL语句执行很慢原因有哪些?其实,这个问题可以涉及到MySQL的很多核心知识,可以扯出一大堆,就像要考你计算机网络的知识时,问你“输入URL回车之后,究竟发生了什么”一样,看看你能说出多少了。本文的作者就是这道面试题的亲历者,他尝试总结了一下:一、开始装逼:分类讨论一条SQL语句执行很慢,那是每次执行很慢呢?还是...

weixin_39845306的博客 83

sql在plsql执行快,在mybatis中很慢

sql在plsql执行快,在mybatis中很慢,无索引

beauty_魅影 5077

sql提出来执行快,mybatis执行sql很慢

sql提出来执行快,mybatis执行sql很慢

yangzhe19931117的博客 4154

oracle执行sql突然变,求助,sql执行突然变,求助各位了

如下sql,以前执行所需时间大概5-6分钟,昨天开始执行了整整一个晚上耗时近8个小时,还望各位大侠指点下sjcj_rydjbxx r,sjcj_fwdjbxx f 两张表都为分区表 r表近1000万的数据,以rzf_xzdxzqh分区,f表近100万数据,以bih_regioncode分区SELECT c.cd_name "街乡名称", r.rs "人数"FROM (SELECT *FROM ...

weixin_30191947的博客 801

解决同一条sql在pl/sql工具中执行很快,在程序中却很慢

今天因为程序设计漏洞,把一张表得数据给truncate掉了,然后再重的过程中发现有一条sql再pl/sql工具执行很快(1秒内),程序中却需要200-300秒。 sql如下: MERGE INTO t_qt_second t1 USING (select d.sn_no ,c.stair_org_id ,c.stair_org_name , a.assetpro_name , a.org_no , a.assetpro_no from t_org_sn a, t_device b, t_org_inf

weixin_45765201的博客 1万+

java执行sql很慢_JavaEE后台开发过程中,为什么会有SQL问题?如何解决?

我昨天刚好碰到一个问题,应用服务器隔一小段时间就自动重启,最后才定位到是查询的问题,生产环境停摆了半天!查询:超过指定时间的SQL查询。查询的危害:轻者影响整个系统性能,重者直接导致服务重启或死机。开始查询记录日志:使用set global slow_query_log=on;开启查询日志记录。然后使用show variables like 'slow%';查找查询相关情况,除了能看到...

weixin_42501688的博客 1843
上一篇: 没有项目经验找工作处处碰壁怎么办
下一篇: 19年暑假实习,我霸面了鹅厂两次。
刀哥谈Java
博客等级 码龄7年 110粉丝 84原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值