加入收藏 | 设为首页 | 会员中心 | 我要投稿 湖南网 (https://www.hunanwang.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 移动互联 > 正文

不看后悔的腾讯面试题:SQL语句为什么执行的很慢?

发布时间:2019-05-28 15:46:34 所属栏目:移动互联 来源:帅地
导读:说真话,这个题目可以涉及到 MySQL 的许多焦点常识,可以扯出一大堆,就像要考你计较机收集的常识时,问你输入URL回车之后,毕竟产生了什么一样,看看你能说出几多了。 之前腾讯口试的真话,也问到这个题目了,不外答的很欠好,之前没去想过相干缘故起因,导致
副问题[/!--empirenews.page--]

说真话,这个题目可以涉及到 MySQL 的许多焦点常识,可以扯出一大堆,就像要考你计较机收集的常识时,问你“输入URL回车之后,毕竟产生了什么”一样,看看你能说出几多了。

之前腾讯口试的真话,也问到这个题目了,不外答的很欠好,之前没去想过相干缘故起因,导致一时之间扯不出来。以是本日,我带各人来具体扯一下有哪些缘故起因,信托你看完之后必然会有所收成,否则你打我。

不看反悔的腾讯口试题:SQL语句为什么执行的很慢?

分类接头:

一条 SQL 语句执行的很慢,那是每次执行都很慢呢?照旧大大都环境下是正常的,无意呈现很慢呢?以是我认为,我们还得分以下两种环境来接头。

  • 大大都环境是正常的,只是无意会呈现很慢的环境。
  • 在数据量稳固的环境下,这条SQL语句一向以来都执行的很慢。

针对这两种环境,我们来说明下也许是哪些缘故起因导致的。

一、针对无意很慢的环境

一条 SQL 大大都环境正常,无意才气呈现很慢的环境,针对这种环境,我认为这条SQL语句的誊写自己是没什么题目的,而是其他缘故起因导致的,那会是什么缘故起因呢?

1、数据库在革新脏页

当我们要往数据库插入一条数据、可能要更新一条数据的时辰,我们知道数据库会在内存中把对应字段的数据更新了,可是更新之后,这些更新的字段并不会顿时同步耐久化到磁盘中去,而是把这些更新的记录写入到 redo log 日志中去,比及空闲的时辰,在通过 redo log 里的日志把最新的数据同步到磁盘中去。

不外,redo log 里的容量是有限的,假如数据库一向很忙,更新又很频仍,这个时辰 redo log 很快就会被写满了,这个时辰就没步伐比及空闲的时辰再把数据同步到磁盘的,只能停息其他操纵,满身心来把数据同步到磁盘中去的,而这个时辰,就会导致我们平常正常的SQL语句溘然执行的很慢,以是说,数据库在在同步数据到磁盘的时辰,就有也许导致我们的SQL语句执行的很慢了。

2、拿不到锁

这个就较量轻易想到了,我们要执行的这条语句,恰恰这条语句涉及到的表,别人在用,而且加锁了,我们拿不到锁,只能逐步守候别人开释锁了。可能,表没有加锁,但要行使到的某个一行被加锁了,这个时辰,我也没步伐啊。

假如要判定是否真的在守候锁,我们可以用 show processlist这个呼吁来查察当前的状态哦,这里我要提示一下,有些呼吁最好记录一下,横竖,我被问了好几个呼吁,都不知道怎么写,呵呵。

下来我们来访说明下第二种环境,我认为第二种环境的说明步崆最重要的。

二、针对一向都这么慢的环境

假如在数据量一样大的环境下,这条 SQL 语句每次都执行的这么慢,那就就要好好思量下你的 SQL 誊写了,下面我们来说明下哪些缘故起因会导致我们的 SQL 语句执行的很不抱负。

我们先来假设我们有一个表,内外有下面两个字段,别离是主键 id,和两个平凡字段 c 和 d。

  1. mysql> CREATE TABLE `t` ( 
  2.   `id` int(11) NOT NULL, 
  3.   `c` int(11) DEFAULT NULL, 
  4.   `d` int(11) DEFAULT NULL, 
  5.   PRIMARY KEY (`id`) 
  6. ) ENGINE=InnoDB; 

1、没用到索引

没有效上索引,我认为这个缘故起因是许多人都能想到的,譬喻你要查询这条语句:

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

1)字段没有索引

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

2)字段有索引,但却没有效索引

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

  1. select * from t where c - 1 = 1000; 

我想问各人一个题目,这样子在查询的时辰会用索引查询吗?

答是不会,假如我们在字段的左边做了运算,那么很歉仄,在查询的时辰,就不会用上索引了,以是呢,各人要留意这种字段上有索引,但因为本身的疏忽,导致体系没有行使索引的环境了。

正确的查询应该如下:

  1. select * from t where c = 1000 + 1; 

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

欠盛意思,确实不会帮你,以是,你要留意了。

3)函数操纵导致没有效上索引

假如我们在查询的时辰,对字段举办了函数操纵,也是会导致没有效上索引的,譬喻:

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

这里我只是做一个例子,假设函数 pow 是求 c 的 n 次方,现实上也许并没有 pow(c,2)这个函数。其拭魅这个和上面在左边做运算也是很相同的。

以是呢,一条语句执行都很慢的时辰,也许是该语句没有效上索引了,不外详细是啥缘故起因导致没有效上索引的呢,你就要会说明白,我上面罗列的三个缘故起因,应该是呈现的较量多的吧。

2、数据库本身选错索引

我们在举办查询操纵的时辰,譬喻:

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

我们知道,主键索引和非主键索引是有区此外,主键索引存放的值是整行字段的数据,而非主键索引上存放的值不是整行字段的数据,并且存放主键字段的值。不大懂的可以看我这篇文章:《口试小常识:MySQL索引相干》,内里有说到主键索引和非主键索引的区别。

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

好吧扯了这么多,着实我就是想汇报你,就算你在 c 字段上有索引,体系也并不必然会走 c 这个字段上的索引,而是有也许会直接扫描扫描全表,找出全部切合 100 < c and c < 100000 的数据。

为什么会这样呢?

(编辑:湖南网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读