文章目录

  • 1 偶尔很慢
  • 1.1 数据库在刷新脏页
  • 1.2 执行的时候遇到锁
  • 2 一直很慢
  • 2.1 没有使用到索引
  • 2.1.1 `字段`没有索引
  • 2.1.2 字段有索引,但是`sql语句`没有使用
  • 2.1.3 `函数操作`导致没有用上索引
  • 2.2 数据库选错了索引



面试的时候就是抻,说得越详细越好。


sql server insert 卡主 执行sql语句卡住_mysql优化


所以得分类讨论。

1 偶尔很慢

1.1 数据库在刷新脏页

往数据库更新数据(增、删、改)的时候,数据库会在内存中把对应的记录更新,但是更新之后,并不会马上同步持久化到磁盘中去,而是把这些更新的记录写入到redo log日记中去,等到空闲时,再通过日记把数据同步到磁盘中去。

1.2 执行的时候遇到锁

被加锁,或者被加锁。
可以用show processlist命令查看是否在等待锁。

2 一直很慢

2.1 没有使用到索引

表结构如下:

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

2.1.1 字段没有索引

此时字段c没有索引,假设要查找如下的记录,则需要全表扫描。

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

2.1.2 字段有索引,但是sql语句没有使用

假设字段c现在已经加上了索引,但是使用如下语句查询,系统仍然会全表扫描。

select * from t where c - 1 = 1000;

正确的语句操作应该是:

select * from t where c = 1000 + 1;

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

同上所示,对字段进行了函数操作,导致没有用上索引

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

2.2 数据库选错了索引

例如,进行如下记录的查找,字段c有索引。

  • 补充一下。主键索引,存放的值是整行字段的数据。非主键索引,存放的是主键字段的值。
select * from t where 100 < c and c < 100000;

因为字段c不是主键,如果走c字段的索引的话,最后会查询到对应主键的值,然后根据主键的值,走主键索引,查询到整行数据返回。
即,就算字段c上有索引,系统也并不一定会走c这个字段上的索引,而是有可能扫描全表,找出符合要求的字段。

参考资料
腾讯面试:一条SQL语句执行得很慢的原因有哪些?—不看后悔系列