还得分两种情况来讨论:
- 大多数情况是正常的,只是偶尔会出现很慢的情况
-
偶尔很慢的情况
数据库在刷新脏页
往数据库插入一条数据或者更新一条数据,数据库会先在内存把对应字段更新了,更新之后并不会立即持久化到磁盘上去,而是先写redo log, 等到空闲的时候,再写磁盘。
redo log的容量是有限的,如果数据库一直很忙,然后更新操作又很频繁,这个时候redo log很快就被写满了,没法等到空闲的时候再把数据同步到磁盘,只能暂停其他操作,全心全意的把数据同步磁盘。拿不到锁
这条SQL语句涉及到的表,别人在用,并且加锁了,我们拿不到锁,只能慢慢等待别人释放锁了。或者,表没有被加锁, 但是使用到的某一行被加锁了,这个时候,也没有办法。
可以使用show processlist 查看当前的状态。针对一直很慢的情况
没用到索引
字段没有索引
字段有索引但是没有用到
select from t where c -1 =1000 正确: select from t where c = 1000 + 1
-
数据库选错索引了
主键索引和非主建索引是有区别的,主键索引存放的是整行字段的数据,非主键索引存放的值不是整行字段的值,而是主键字段的值,
mysql执行的时候,会预测扫描行数,扫描行数越少,磁盘IO越少。可能走全表扫描时是不走索引的,那么系统是怎么判断的呢?索引区分度。一个索引上不同的值越多,区分度越高,称之为基数。区分度越高,基数越大。
怎么知道索引的基数?
采样预测。
其他: force index(a) 强制搜索引
也可以通过show index from t 来查询索引的基数和实际是否符合,不符合的话,可以重新统计索引的基数,
analyze table t