慢SQL问题相信大部分开发都遇到过,对于这样的问题通常第一反应就是看看sql是否合理,比如:
- 避免使用IN和NOT IN,否则可能会导致全表扫描
- 避免在where子句中对字段进行函数操作
- 避免在where子句中对字段进行左模糊查询
- 避免在where子句中对字段进行OR连接
- 避免SELECT *
- ...
除此之外,还有一种常见的反应就是这个表有没有加索引?绝大部分情况下,加了个索引基本上就搞定了。
首先就来构造一个千万级的表直观感受下。创建一张user表,然后新增1000万条数据,查询一下:
用了近30秒的时间,这还是单表查询,关联查询明显会更慢。接下来,将id设为索引,再来验证:
从30s到0.02s,提升了足足1500倍。为什么加了索引之后,速度一飞冲天了呢?下面从索引结构和MySQL原理两个方面入手。
一、索引数据结构
先来看下 MySQL官方对索引的定义:
索引(Index)是帮助MySQL高效获取数据的数据结构。
这里面有两个关键词:高效获取、数据结构。对于数据库来说,查询是最主要的使用功能,查询速度肯定是越快越好。最基本的查找是顺序查找,更高效的查找很自然会想到二叉树、红黑树、Hash表、BTree等。
1.1 二叉树
特点:
- 左边节点的键值小于根的键值
- 右边节点的键值大于根的键值。
如图1,它确实能明显提高搜索性能,但如果用来作为数据库的索引,明显存在很大的缺陷。对于图2这种递增的id,存储后索引近似于变成了单边的链表,显然是不合适的。
图1