快速,持续,稳定,傻瓜式
支持Mysql,Sqlserver数据同步

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

请联系QQ:1793040 索取软件

在最近的招聘季节,腾讯遇到了一个采访问题:SQL语句执行缓慢的原因是什么?

实际上,这个问题涉及MySQL的很多核心知识,可以将其抽出很多,就像当您想测试计算机网络知识时,问您”输入URL后会发生什么?然后按Enter键。再次查看您能说多少。

本文的作者是经历此面试问题的人。他试图对其进行总结:

SQL语句的执行速度非常慢。每次执行速度慢吗?还是在大多数情况下是正常现象,偶尔会缓慢出现?因此,我认为,我们还对以下两种情况进行了讨论。

1.大多数情况都是正常的,但偶尔会非常缓慢。

2.在数据量恒定的情况下,此SQL语句的执行速度非常慢。

对于这两种情况,让我们分析可能的原因。

A? SQL?大多数情况是正常的,有时非常缓慢。对于这种情况,我认为编写此SQL语句本身不是问题,而是由其他原因引起的,原因是什么?

当我们想向数据库中插入一条数据或更新一条数据时,我们知道数据库将更新内存中的相应字段数据,但是在更新之后,这些数据将更新字段不会立即同步并保留到磁盘,而是将这些更新的记录写入重做日志日志。空闲时,最新数据将同步到磁盘

当内存数据页和磁盘数据页的内容不一致时,我们将此内存页称为”脏页”。将内存数据写入磁盘后,内存和磁盘上数据页面的内容相同,称为”干净页面”。

有以下四种情况可以清除脏页(后两种情况无需过多关注”性能”问题):

  • 重做日志已满:重做日志的容量受到限制。如果数据库总是很忙并且经常更新,则这次重做日志很快就会装满。这次没有办法等到空闲时将数据同步到磁盘。您只能暂停其他操作,并专注于磁盘上的数据。此时,会导致我们正常的普通SQL语句突然执行,因此,当数据库将数据同步到磁盘时,它可能导致我们的SQL语句执行非常慢。

  • 内存不足:如果一次查询很多数据,则当您要检查的数据页不在内存中时,您需要申请内存,而当它不存在时,则需要将其消除碰巧是内存不足。部分内存数据页,如果是干净页,则直接释放,如果碰巧是脏页,则需要刷新脏页。

  • 当MySQL认为系统为”空闲”时:此时,系统没有受到压力。

  • 当MySQL正常关闭时:此时,MySQL会将所有内存的脏页刷新到磁盘上,以便MySQL下次启动时,可以直接从磁盘读取数据并启动速度会非常快。

这很容易想到。我们要执行的语句,只是该语句中涉及的,正在被其他人使用并被锁定,我们无法获取该锁,只能慢慢地等待其他人释放该锁。或者,表未锁定,但是要使用的行被锁定。在这个时候,我别无选择。

如果要判断您是否真的在等待锁,我们可以使用 show processlist 命令来检查当前状态。在此我想提醒您,最好记录一些命令。无论如何,我被问了几个命令后,我不知道该怎么写,呵呵。

让我们访问并分析第二种情况。我认为对第二种情况的分析是最重要的。

如果这样? SQL?每次数据量相同时,语句执行速度如此缓慢,那么您应该仔细考虑一下吗? SQL?写完之后,让我们分析一下将导致什么原因。执行我们的?SQL?语句并不理想。

首先,我们假设我们有一个包含以下两个字段的表,即主键? id和两个普通字段? C?和? d。

没有使用索引,我认为这是很多人可以想到的原因,例如,您要查询此语句

(1),该字段没有索引

碰巧您没有索引吗? C?字段,所以很抱歉,您只能执行全表扫描,您将体验到不编制索引的乐趣,因此这一次此查询语句非常慢。

(2),该字段具有索引,但未使用该索引

好的,这时您将索引添加到字段c中,然后查询另一条语句

我想问你一个问题,所以查询时会使用索引查询吗?

答案是否定的。如果我们在字段左侧进行计算,那么很抱歉我们在查询时不会使用索引,因此请注意此字段上的索引,但是由于自身的疏忽,系统没有使用索引

正确的查询应如下所示

有人会说在使用索引的权利上有一项操作?数据库不是自动帮助我们对其进行优化并自动转换吗?C?-?1 = 1000?To?C?=?1000 +1。

抱歉,我不会帮您,所以您应该注意。

(3),该函数操作导致不使用索引

如果在查询过程中对字段执行函数操作,也会导致索引未使用,例如

在这里我只是举一个例子,假设该函数?战俘?是力量? n?的? c?,实际上可能没有?战俘(c,2)。实际上,这与左侧的计算非常相似。

因此,当一条语句的执行速度非常慢时,可能是该语句未用于索引,但是未使用索引的具体原因,您将对其进行分析,这是我上面列出的三个原因是它出现的频率更高。

例如,当我们执行查询操作时

我们知道主键索引与非主键索引不同。存储在主键索引中的值是整个行字段的数据,存储在非主键索引中的值不是整个行字段的数据。并存储主键字段值

就是说,如果我们去索引? c′,最后查询对应的主键值,然后根据主键值查询主键的索引,并返回整行数据。

好吧,事实上,我只是想告诉您,即使您有索引吗? C?现场,系统不一定去吗? C?该字段上的索引可能是直接扫描整个表以查找所有符合条件的数据? 100? \ Lt ; C?和? C? \ Lt ; 100000?。

为什么会这样?

实际上是这种情况。当系统执行该语句时,它将做出一个预测:它将继续吗? C?索引扫描中的行数少还是全表扫描中的行数少?显然,扫描线的数量越少越好,因为扫描线的数量越少,I/O操作的数量就越少。

如果扫描整个表,则假设扫描次数是该表中的总行数。 n;如果你去索引? c ,通过索引找到主键之后? C?主键索引用来查找我们的整个数据行,也就是说,我们需要遍历两次索引。而且,我们不知道有多少行数据满足条件? 100? C? \ Lt ;和? C? \ Lt ; 10000?,如果满足此表中的所有数据怎么办?这个时候意味着走路了吗? C?索引不仅扫描行数,而且还必须为每行数据遍历两次索引。

因此,系统可能无需索引就可以执行全表扫描。系统如何判断?

判断来自系统的预测,也就是说,如果要转到c?字段索引,系统将预测要扫描多少行?如果预测要扫描的行数很大,它可以直接扫描整个表而无需编制索引。

然后问题来了,系统如何预测和判断? 在这里,我将告诉您系统的判断方式,尽管此时我已经写到我的脖子有点酸。

系统由索引判别进行判断。索引上的值越多,具有相同值的索引越少,这意味着索引判别率越高。我们也将歧视程度称为基数,即,歧视程度越高,基数越大。那么,基数越大,满足条件的行数越少? 100? \ Lt ; C?和? C? \ Lt ; 10000吗?

因此,索引的基数越大,索引查询的优势就越大。

然后问题来了,您如何知道该索引的基数?

当然,系统不会遍历所有以获得索引基数,成本太高,索引系统会通过遍历部分数据(即通过采样)来预测索引的基数

太多了,关键就来了,实际上是抽样,那么可能会有错误,即c?该索引的基数实际上很大,但不幸的是,在采样时,该索引的基数预计很小。例如,您采样的数据部分的基数很小,您错误地认为索引的基数很小。 然后,系统将不会转到c索引,而只会扫描全部

因此,在说了这么多之后,我得出了一个结论:由于统计错误,系统没有采用索引,而是进行了全表扫描,这还引起了我们吗? SQL?语句执行缓慢的原因。

在这里,我声明系统判断是否采用索引。扫描行数的预测实际上只是原因之一。该查询语句是否需要使用临时表或是否需要排序也将影响系统的选择。

但是,有时我们也可以通过强制索引进行查询,例如

我们也可以通过

要检查索引的基数是否与实际匹配,如果与实际不符,我们可以重新计算索引的基数,可以使用此命令

重新统计分析。

由于将预测错误索引的基数,因此这也意味着当我们的查询具有多个索引时,系统可能还会选择错误的索引。 这还可能吗? SQL执行缓慢的原因之一?

好吧,先拉很多,然后再拉很多,我认为它已经很棒了,下面总结一下。

第四,总结

以上是我的总结和理解。在最后一部分,恐怕很多人不理解。 数据库将选择错误的索引,因此我对其进行了详细说明。让我总结一下以上内容。

一个SQL实现非常慢,我们需要讨论两种情况:

1.在大多数情况下,这是正常现象,但偶尔会很慢,原因如下

(1)。数据库正在刷新脏页。例如,?重做?日志?已满,需要同步到磁盘。

(2)在执行期间,遇到了表锁和行锁之类的锁。

2.这个? SQL?由于以下原因,该语句的执行速度非常慢。

(1),不使用索引:例如,该字段没有索引;由于该字段的操作和功能操作,无法使用该索引。

(2)在数据库中选择了错误的索引。

如果要添加任何内容,还可以在消息区域中添加波浪。

由于篇幅所限,所有需要信息的朋友都可以向我添加Q组809389099以免费访问

 10a ¥ 40?¥?o30?¤a-é?é·¥?3è?è

数据收集方法:关注+喜欢并加入我的Q小组免费获取它!

相关推荐

 
QQ在线咨询
售前咨询热线
QQ1793040