详细介绍MySQL的索引(上)

索引

索引概述

索引(index)是帮助MySQL高效获取数据的数据结构(有序)。在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向数据,这样就可以在这些数据结构上实现高级查找算法,这种数据结构就是索引。

索引的优缺点

优点 : 提高数据检索的效率,降低数据库的lO成本;

通过索引列对数据进行排序,降低数据排序的成本,降低CPU的消耗。

缺点: 索引列也是要占用空间的;

索引大大提高了查询效率,同时却也降低更新表的速度,如对表进行INSERT、 UPDATE、DELETE时,效率降低。

索引结构

索引是在MySQL的体系结构中的存储引擎层实现的。因此选择不同的存储引擎,索引的结构也会不同,主要包含以下几种:

B+Tree索引:最常见的索引类型,大部分引擎都支持B+树索引。

Hash索引:底层数据结构是用哈希表实现的,只有精确匹配索引列的查询才有效,不支持范围查询。

R-tree(空间索引):空间索引是MyISAM引擎的一个特殊索引类型,主要用于地理空间数据类型,通常使用较少。

Full-text(全文索引):是一种通过建立倒排索引,快速匹配文档的方式。类似于Lucene,Solr,ES。

下面列举市面上较为常见的存储引擎对索引的支持情况:

推荐一个可以动态演示数据结构的网址:Data Structure Visualization (usfca.edu)https://www.cs.usfca.edu/~galles/visualization/Algorithms.html

普通二叉树结构:

二叉树缺点:顺序插入时,会形成一个链表,查询性能大大降低。大数据量情况下,层级较深,检索速度慢。

红黑树:大数据量情况下,层级较深,检索速度慢。

B-Tree(多路平衡查找树):

B+Tree

相对于B-Tree区别:

①.所有的数据都会出现在叶子节点。

②.叶子节点形成一个单向链表。

在MySQL的B+Tree中

Hash索引的存储结构:

哈希索引就是采用一定的hash算法,将键值换算成新的hash值,映射到对应的槽位上,然后存储在hash表中。

如果两个(或多个)键值,映射到一个相同的槽位上,他们就产生了hash冲突(也称为hash碰撞),可以通过链表来解决

Hash索引的特点:

  1. Hash索引只能用于对等比较(=,in),不支持范围查询(between,>,<,..)。

2.无法利用索引完成排序操作(因为Hash运算出来的结果是无序的)。

3.查询效率高,通常只需要一次检索就可以了(前提不出现Hash碰撞,不然得在链表中查找),效率通常要高于B+tree索引。

存储引擎的支持

在MysQL中,支持hash索引的是Memory引擎,而innoDB中具有自适应hash功能,hash索引是存储引擎根据B+Tree索引在指定条件下自动构建的。

这样就会出现一道面试题

为什么InnoDB引擎选择使用B+Tree索引结构?

答 :

相对于二叉树,层级更少,搜索效率高;

对于B-tree,无论是叶子节点还是非叶子节点,都会保存数据,这样导致一页中存储的键值减少,指针跟着减少,要同样保存大量数据,只能增加树的高度,导致性能降低;

相对Hash索引,B+tree支持范围匹配及排序操作;

索引分类

索引的分类一般会分为四类:

主键索引:针对于表中主键创建的索引,默认自动创建,只能有一个。

唯一索引:避免同一个表中某数据列中的值重复,可以有多个。

常规索引:快速定位特定数据,可以有多个。

全文索引:全文索引查找的是文本中的关键词,而不是比较索引中的值,可以有多个。

在InnoDB存储引擎中,根据索引的形式,又可以分为以下两种:

聚集索引(Clustered Index):将数据存储与索引放到了一块,索引结构的叶子节点保存了行数据,必须有,而且只有一个。

二级索引(Secondary Index):将数据与索引分开存储,索引结构的叶子节点关联的是对应的主键,可以存在多个。

聚集索引的选取规则

如果存在主键,主键索引就是聚集索引。

如果不存在主键,将使用第一个唯一(UNIQUE)索引作为聚集索引。

如果表没有主键,或没有合适的唯一索引,则InnoDB会自动生成一个rowid作为隐藏的聚集索引。

索引语法

创建索引:

sql 复制代码
CREATE[ UNIQUE | FULLTEXT ] INDEX index_name ON table_name ( index_col_name,...);

查看索引:

sql 复制代码
SHOW INDEX FROM table_name;

删除索引:

sql 复制代码
DROP INDEX index_name ON table_name;

SQL性能分析

我们在大多数情况下对SQL进行优化的场景是查询场景,因此如何知道一张表的DML语句分别执行了多少次尤为重要。

SQL的执行频率
sql 复制代码
SHOW GLOBAL STATUS LIKE 'Com_______'
慢查询日志

检查慢查询日志是否开启

sql 复制代码
SHOW VARIABLES LIKE 'slow_query_log';

慢查询日志记录了所有执行时间超过指定参数(long_query_time,单位:秒,默认10秒)的所有SQL语句的日志。

MySQL的慢查询日志默认没有开启,需要在MySQL的配置文件(/etc/my.cnf)中配置如下信息:

profile详情

show profiles能够在做SQL优化时帮助我们了解时间都耗费到哪里去了。通过have profiling参数,能够看到当前MySQL是否支持。

sql 复制代码
SELECT @@have_profiling;

默认profiling是关闭的,可以通过set语句在session/global级别开启profiling。

查看profiling是否打开 1 代表打开,0 代表关闭。

sql 复制代码
SELECT @@profiling;

打开profiling的命令:

sql 复制代码
SET profiling = 1;

查看执行的SQL语句的耗时情况:

sql 复制代码
SHOW PROFILES;

查看指定query_id的SQL语句各个阶段的耗时情况

sql 复制代码
show profile for query query_id;
explain执行计划

EXPLAIN或者DESC命令获取MySQL如何执行SELECT语句的信息,包括在SELECT语句执行过程中表如何连接和连接的顺序。

语法:


下篇文章会给大家带来索引的使用原则和关于如何设计索引。

相关推荐
水题检测鸟18 分钟前
乐观锁与悲观锁
数据库
Majoy21 小时前
HBase
大数据·数据库·hbase
夜光小兔纸2 小时前
oracle查询出表中某几个字段值不唯一的数据
数据库·sql·oracle
deadknight94 小时前
Oracle密码过期处理方式
数据库·oracle
Ljubim.te4 小时前
数据库第01讲章节测验(选项顺序可能不同)
数据库
吱吱喔喔4 小时前
数据分表和分库原理
数据库·分表·分库
快乐非自愿4 小时前
KES数据库实践指南:探索KES数据库的事务隔离级别
数据库·oracle
一只fish4 小时前
Oracle的RECYCLEBIN回收站:轻松恢复误删对象
数据库·oracle
weixin_440401694 小时前
分布式锁——基于Redis分布式锁
java·数据库·spring boot·redis·分布式
TOR-NADO4 小时前
数据库概念题总结
数据库·oracle