加快查找数据的速度
- 减少服务器扫描行数。
- 避免进行排序和分组,以及避免创建临时表
- 将随机 I/O 变为顺序 I/O。
- 适用中大型表;
- 不适用小表和超大表。因为小表没必要建索引,超大表的维护代价太高。
聚集索引与非聚集索引的区别是:叶节点是否存放一整行记录。
InnoDB引擎中主键使用的是聚簇(主)索引,非主键索引用非聚簇(辅助)索引。 MyISAM不管是主键还是非主键索引使用的都是非聚簇索引。
- 聚簇索引: 叶子节点 data 域记录着完整的数据记录。因为无法把数据行存放在两个不同的地方,所以一个表只能有一个聚簇索引。
- 非聚簇索引: 叶子节点的 data 域记录着主键的值,因此在使用辅助索引进行查找时,需要先查找到主键值,然后再到主索引中进行查找。
MySQL数据库支持多种索引类型,如BTree索引,B+Tree索引,哈希索引,全文索引等等,它们的原理如下:
B+ Tree索引是MySQL存储引擎的默认索引。 可以用于查找,分组,排序。
B+ Tree 是一棵平衡M叉查找树。
- B+ Tree中叶子节点会记录所有的值,非叶子节点的作用是指定范围,不会保存值。
- B Tree中的非叶子节点会记录值。
- B+ Tree的优点:
- 顺序访问叶子节点,减少单次查询的磁盘访问次数,来提高区间查询的性能。
- 更少的查找次数 红黑树是二叉树,导致同样数量的data,红黑树的高度会大于B+树。
- 减少磁盘寻道 因为磁盘不是严格读取数据,而是会有预读的情况。顺序读取的过程中不需要磁盘寻道,速度更快。
哈希索引是基于哈希表实现的,只支持等值比较的查询,不支持任何范围查询。 哈希索引中会存储每行记录的哈希值和数据的指针,不存储字段值。
- 优点:速度快,只需要很小索引就可以为比较长的key创建索引。
- 缺点:
-
无法排序,不支持范围查询:因为不是按照值的存储顺序存储的
-
不支持匹配查找:因为存储的是哈希值
-
不能利用部分索引键查询
-
哈希冲突比较多的时候,维护代价高
当某个索引值被使用的非常频繁时,会在 B+Tree 索引之上再创建一个哈希索引,这样就让 B+Tree 索引具有哈希索引的一些优点,比如快速的哈希查找。
- 特点:由InnoDB决定是否创建,用户无法控制或者配置,可以选择关闭该功能。
如果引擎不支持哈希索引,可以自己创建。
- 应用场景:索引key比较大,只需要精准查找。 例如,需要存储大量的URL,并根据URL进行查找。 这时可以
- 在建表的时候建一个url_crc字段; 注意,不要用SHA1和MD5作为哈希函数,因为加密后长度太长;可以用CRC32,但是如果表比较长,可以自己实现一个64位哈希算法。
- 触发器,在插入和更新时维护url_crc字段;
- 避免冲突: select的时候,where条件中除了带哈希值,还需要带对应的列值,如下
select * from user where crc = CRC32('https://waiting.com') and url = 'https://waiting.com'
全文索引用于查找文本中的关键词,而不是直接比较是否相等。
- 文本比较少情况下,可以用like + % 实现模糊查询;
- 大量文本检索的时候,需要用全文索引,因为他的速度是like的N倍。
- 引擎:MyISAM 或者 InnoDB(version>5.6)
- 支持全文索引的数据类型:char、varchar、text
MySQL 5.6.4版本以后的InnoDB和所有的MyISAM 版本支持全文索引。 利用倒排索引实现的。
空间数据索引会从所有维度来索引数据,主要用于地理数据存储。 MyISAM 存储引擎支持空间数据索引(R-Tree)。
- id: SELECT 查询的标识符. 每个 SELECT 都会自动分配一个唯一的标识符.
- select_type: SELECT 查询的类型.
- table: 查询的是哪个表
- partitions: 匹配的分区
- type: join 类型
- possible_keys: 此次查询中可能选用的索引
- key: 此次查询中确切使用到的索引.
- ref: 哪个字段或常数与 key 一起被使用
- rows: 显示此查询一共扫描了多少行. 这个是一个估计值.
- filtered: 表示此查询条件所过滤的数据的百分比
- extra: 额外的信息
select_type 表示了查询的类型, 它的常用取值有:
- SIMPLE, 表示此查询不包含 UNION 查询或子查询
- PRIMARY, 表示此查询是最外层的查询
- UNION, 表示此查询是 UNION 的第二或随后的查询
- DEPENDENT UNION, UNION 中的第二个或后面的查询语句, 取决于外面的查询
- UNION RESULT, UNION 的结果
- SUBQUERY, 子查询中的第一个 SELECT
- DEPENDENT SUBQUERY, 子查询中的第一个 SELECT, 取决于外面的查询. 即子查询依赖于外层查询的结果.
type 判断此次查询是全表扫描还是索引扫描等.
type 类型的性能比较, 不同的type类型的性能关系如下: ALL < index < range ~ index_merge < ref < eq_ref < const < system 其中:
- ALL 是全表扫描,是速度最慢的.
- index 是扫描了所有的索引, 比 ALL 类型稍快.
- 后面的几种类型都是利用了索引来查询数据,可以过滤大部分数据, 因此效率比较高.
EXplain 中的很多额外的信息会在 Extra 字段显示, 常见的有以下几种内容:
- Using filesort 当 Extra 中有 Using filesort 时, 表示 MySQL 需额外的排序操作, 不能通过索引顺序达到排序效果. 一般有 Using filesort, 都建议优化去掉, 因为这样的查询 CPU 资源消耗大.
- Using index "覆盖索引扫描", 表示查询在索引树中就可查找所需数据, 不用扫描表数据文件, 往往说明性能不错
- Using temporary 查询有使用临时表, 一般出现于排序, 分组和多表 join 的情况, 查询效率不高, 建议优化.