mysql怎么查看刷脏页慢_MySQL查询数据慢原因

针对一直都这么慢的情况

如果在数据量一样大的情况下,这条 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 

a. 字段没有索引

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

b.字段有索引,但却没有用索引

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

select * from t where c - 1 = 1000;

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

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

正确的查询应该如下

select * from t where c = 1000 + 1;

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

c. 函数操作导致没有用上索引

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

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

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

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

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

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

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

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

思维导图

2bbb9a3074727fc8a41ba9701290e5a9.png

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

就算你在 c 字段上有索引,系统也并不一定会走 c 这个字段上的索引,而是有可能会直接扫描扫描全表,找出所有符合 100 < c and c < 100000 的数据。

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

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

系统是通过索引的区分度来判断的,一个索引上不同的值越多,意味着出现相同数值的索引越少,意味着索引的区分度越高。我们也把区分度称之为基数,即区分度越高,基数越大。所以呢,基数越大,意味着符合 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. 大多数情况下很正常,偶尔很慢,则有如下原因

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

b. 执行的时候,遇到锁,如表锁、行锁。

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

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

b. 数据库选错了索引。

按键查找还是比较常见的性能提升手段。 个人总结的优化原则是: 做事快(索引、并行、快盘、高效表连接等) 做事少(数据拆分减少访问数据量、过滤性强的条件、去除或降低不必要执行的语句量等) 无等待(热块打散、锁争用避免等)

出处:https://juejin.im/post/5cc84cb6518825250e146c61

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MySQL 的 bigint 类型是一种大整数类型,其范围为 -9223372036854775808 到 9223372036854775807。如果您在使用 MySQL 数据库时遇到了查询的问题,可以尝试以下方法: 1. 确认索引是否合理 在 MySQL 中,索引是提高查询效率的重要手段。如果您的表中存在 bigint 类型的字段,并且您的查询语句中使用了该字段作为条件,那么建立相应的索引可以大大提高查询效率。 使用以下命令检查索引是否合理: ``` SHOW INDEX FROM table_name; ``` 如果没有相应的索引,可以使用以下命令创建索引: ``` CREATE INDEX index_name ON table_name (column_name); ``` 2. 避免全表扫描 全表扫描是一种低效的查询方式,会导致查询效率低下。因此,应尽量避免使用全表扫描。 例如,如果您要查询表中某个 bigint 类型的字段的值是否等于某个值,可以使用以下语句: ``` SELECT * FROM table_name WHERE column_name = 123456; ``` 而不是使用以下语句: ``` SELECT * FROM table_name WHERE column_name; ``` 3. 优化查询语句 优化查询语句也是提高查询效率的一种方法。您可以使用 EXPLAIN 命令来查看查询语句的执行计划,并根据执行计划来进行优化。 例如,以下查询语句可能会导致查询效率低下: ``` SELECT * FROM table_name WHERE column_name LIKE '%keyword%'; ``` 可以优化为: ``` SELECT * FROM table_name WHERE column_name LIKE 'keyword%'; ``` 4. 调整 MySQL 配置参数 在 MySQL 中,有一些配置参数可以影响查询效率。您可以根据实际情况调整这些参数来提高查询效率。 例如,以下参数可以影响查询效率: - innodb_buffer_pool_size:控制 InnoDB 存储引擎使用的内存池大小。 - query_cache_size:控制查询缓存的大小。 - join_buffer_size:控制连接缓存的大小。 调整这些参数时,请注意不要将它们设置得过高或过低,以免影响系统的稳定性和性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值