数据库的一些问题+答案(持续更新)

SQL 语句查询慢

  遇到这种问题无非就两种情况:一、大部分情况下都是执行的很快,偶尔需要很长时间。二、SQL 语句一直都执行得很慢。接下来将对这两种情况进行详细分析。

  一、偶尔执行很慢

        大部分情况下执行都是正常得,部分时间执行很慢,首先可能确认 SQL 语句本身是没有多大的问题的,那是什么原因呢?

    1、数据库在刷新脏页

    脏页 是指当内存中的数据页和磁盘数据页中的不一致时,我们把内存数据页称作“脏页”;否则称之为“干净页”。

        当我们对数据库进行更新操作(增、删、改等)时,数据库首先会在内存中对数据进行更新,但这并不会直接同步到磁盘中,而是把这些更新的记录写道 redo log 日志中去,然后等系统空闲时再写到磁盘中。

    刷新脏页的情况:

      • redo log写满了,和其他容器一样,redo log 的容量也是有限的,当我们一直对数据库进行操作,redo log 很快就会被写满,这时数据库就不能等到系统空闲时刷新脏页了,就只能暂停其他操作,尽快把数据同步到磁盘当中,因此,有时候我们的 SQL 语句执行的会比较慢的情况
      • 内存不够用了,上面介绍了,数据库会在内存中进行操作,当我们一次性查询很多数据,而这些数据都不在内存当中,更可恶的是此时的内存不够用了,这时候就需要释放一部分内存数据页,如果这些数据页都是脏页,那么将刷新脏页;如果是干净页的话直接释放就好了。
      • MySQL 认为系统空闲,这时候就会刷新脏页了。
      • MySQL 正常关闭,当数据库关闭的时候,会把脏页刷新到磁盘中,在下一次启动时,直接从磁盘中读取数据。

    2、拿不到锁

          这个应该很好理解吧,数据库有各种锁,当我们执行一条语句的时候,可能会需要某种锁,但此时有其他用户在使用这个锁,那很无奈啊,只能等别人用完释放锁了。

  二、一直执行很慢

        在数据量一定的情况下,如果你的 SQL 语句执行的很慢,你就要好好想想你的 SQL 语句了。
     1、没有用到索引

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

        数据库在执行语句的时候,会进行一个预测:走索引扫描的行数少还是直接全表扫描的行数少?扫描行数越少也好,扫描行数越少,I/O操作的次数也就越少。
        主键索引存放的值是整行字段的数据,而非主键索引上存放的值不是整段的数据,而是主键字段的值。如果查询走非主键字段,会先查询对应主键的值,然后再走一遍主键索引,然后查询到整行数据。

    系统怎么预测判断呢?

        系统是通过索引的区分度来判断的,一个索引上不同的值越多,意味着出现相同数值的索引越少,意味着索引的区分度越高。我们也把区分度称之为 基数 ,即 区分度越高,基数越大

        系统怎么获取这个索引的基数呢? 通过采样的办法,遍历部分数据。采样的方式可能会出现失误,一个索引的基数实际上可能很大,但在采样的过程中,很不幸,数据库遍历了那份基数很小的。然后就直接全表扫描了。

 

posted @ 2020-11-24 17:51  菠菜不要香菜  阅读(295)  评论(0编辑  收藏  举报