目录
1.索引概述
索引(index)是帮助MysQL
高效获取数据的数据结构
(有序
)。在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法,这种数据结构就是索引。
优缺点:
2.索引结构
MySQL的索引是在存储引擎层实现的,不同的存储引擎有不同的结构,主要包含以下几种:
在不同存储引擎下的支持情况:
我们平常所说的索引,如果没有特别指明,都是指
B+树结构
组织的索引。
1.B树(多路平衡查找树)
采用B树的原因:
①二叉树缺点:顺序插入时,会形成一个链表,查询性能大大降低。
大数据量情况下,层级较深,检索速度慢。
②红黑树:大数据量情况下,层级较深,检索速度慢。
B树是一种
高度平衡
的搜索树,用于在大型数据集上进行快速查找、插入和删除操作。它通过将多个键值对存储在一个节点中,并引入了一个概念------阶数(order),来保持树的平衡。
B树具有以下特点
:
- 每个节点最多包含m个子节点(m>=2),且每个节点(除了根节点)至少包含
m/2
个子节点。- 所有叶子节点位于同一层,且包含的关键字数目在
[m/2−1, m−1]
范围内。- 非叶子节点的关键字按升序排列,并把它们分割成
m-1
个键值,并在相应的位置存储指向子节点的指针。- 通过使用指针(指向子节点或者兄弟节点)来加快搜索速度。
B树的平衡性使得在进行查找、插入和删除等操作时,每次操作所需的时间复杂度都为 O ( l o g n ) O(log n) O(logn),其中n为树中节点的数量。因此,
B树常用于操作大型数据库
和文件系统的索引结构。
2.B+树
B+树是一种常用的索引结构,用于在
数据库中高效地存储和查找数据
。它是一种多路搜索树,每个节点可以存储多个关键字和对应的数据指针。
B+树的特点
如下:
树中的每个节
点最多可以有m个子节点
,并且满足 m>=2。根节点至少有两个子节点。
所有叶子节点都在同一层
,且不存储数据,只存储关键字和数据的指针。非叶子节点的关键字按照从小到大的顺序排列,且每个关键字对应的子树中的所有关键字都大于等于该关键字。
非叶子节点的关键字个数比子节点的个数少1,即一个内部节点有k个关键字,则它有k+1个子节点。
通过非叶子节点可以进行索引查询,最终的结果必须从叶子节点获取。
B+树的优点
:B+树的层级较低,查询速度快,尤其适用于范围查询。
B+树的叶子节点形成了一个
有序链表
,便于范围查询和遍历。B+树的非叶子节点上存储的是关键字,而
叶子节点上存储的是数据和关键字的指针
,使得查询效率更高。
B+树广泛应用
于数据库系统的索引结构和文件系统的索引结构中,能够提高数据的检索效率。
MySQL索引数据结构对经典的B+Tree进行了优化
。在原B+Tree的基础上,
增加一个指向相邻叶子节点的链表指针
,就形成了带有顺序指针的B+Tree,提高区间访问的性能。(双向链表
)
3.Hash
哈希索引
就是采用一定的hash算法,将键值换算成新的hash值,映射到对应的槽位上,然后存储在hash表中。如果两个(或多个)键值,映射到一个相同的槽位上,他们就产生了
hash冲突
(也称为hash碰撞
),可以通过链表
来解决。
1.特点
①Hash索引只能用于
对等比较
(=,in),不支持范围查询
(between,>,<,...)②无法利用索引完成排序操作
③
查询效率高
,通常只需要一次检索就可以了,效率通常要高于B+tree
索引
2.存储引擎支持
在MySQL中,
支持hash索引的是Memory引擎
,而InnoDB中具有自适应hash
功能,hash索引是存储引擎根据B+Tree索引在指定条件下自动构建的。
4.选择B+树作为InnoDB存储引擎索引结构的原因
①相对于二叉树,
层级更少,搜索效率高
;②对于
B-tree
,无论是叶子节点还是非叶子节点,都会保存数据,这样导致一页中存储的键值减少,指针跟着减少
,要同样保存大量数据,只能增加树的高度,导致性能降低
;③相对Hash索引,
B+tree支持范围匹配及排序操作
;
3.索引分类
在InnoDB存储引擎中,根据索引的存储形式,又可以分为以下两种:
1.聚集索引选取规则
①如果存在主键,
主键索引
就是聚集索引。②如果不存在主键,将使用
第一个唯一(UNIQUE)索引
作为聚集索引。③如果表没有主键,或没有合适的唯一索引,则InnoDB会
自动生成一个rowid
作为隐藏的聚集索引。
2.回表查询
回表查询指的是当数据库在查询过程中,需要
通过索引找到对应的行,然后再根据行的指针回到数据块中去获取数据
的过程。常见的情况是,当使用非聚集索引进行查询时,数据库会首先通过索引找到对应的行所在的数据块,然后再从数据块中读取该行的数据。
这个过程中,数据库需要进行多次访问磁盘,因此被称为回表查询。
回表查询的效率一般较低,而且会增加系统的IO负载。
4.索引语法
1.创建索引
sql
CREATE [UNIQUE|FULLTEXT] INDEX index_name ON table_name (index_col_name,...);
2.查看索引
sql
SHOW INDEX FROM table_name;
3.删除索引
sql
DROP INDEX index_name ON table_name;
5.SQL性能分析
1.SQL执行频率
MySQL客户端连接成功后,通过
show [session | global] status
命令可以提供服务器状态信息。通过如下指令,可以查看当前数据库的INSERT、UPDATE、DELETE、SELECT的访问频次:
sql
SHOW GLOBAL STATUS LIKE 'Com_______'; -- 七个下划线
2.慢查询日志
慢查询日志记录了所有执行时间超过指定参数(long_query_time,单位:秒,默认10秒)的所有SQL语句的日志。
MySQL的慢查询日志
默认没有开启
,需要在MySQL的配置文件(/etc/my.cnf
)中配置如下信息:
配置完毕之后,通过以下指令
重新启动MySQL
服务器进行测试,查看慢日志文件中记录的信息
/var/lib/mysql/localhost-slow.log
.
3.profile详情
show profiles能够在做SQL优化时帮助我们了解时间都耗费到哪里去了。
通过have_profiling参数,能够看到当前MySQL是否支持profile操作:
sql
SELECT @@have_profiling;
默认profiling是关闭的
,可以通过set语句在session/global
级别开启profiling:
sql
SET profiling = 1;
执行一系列的业务SQL的操作,然后通过如下指令查看指令的执行耗时:
4.explain执行计划
EXPLAIN
或者DESC
命令获取MySQL如何执行SELECT语句的信息,包括在SELECT语句执行过程中表如何连接和连接的顺序。
EXPLAIN执行计划各字段含义:
①
Id
:select查询的序列号,表示查询中执行select子句或者是操作表的顺序(id相同,执行顺序从上到下
;id不同,值越大,越先执行
)。②
select_type
:表示SELECT的类型,常见的取值有SIMPLE(简单表,即不使用表连接或者子查询)、PRIMARY(主查询,即外层的查询)、UNION(UNION中的第二个或者后面的查询语句)、SUBQUERY (SELECT/WHERE之后包含了子查询)等③
type
:表示连接类型,性能
由好到差的连接类型为NULL、system、const、eq_ref、ref、range、index、all 。④
possible_key
:显示可能应用在这张表上的索引,一个或多个。⑤
Key
:实际使用的索引,如果为NULL,则没有使用索引。⑥
Key_len
:表示索引中使用的字节数,该值为索引字段最大可能长度,并非实际使用长度,在不损失精确性的前提下,长度越短越好。⑦
rows
:MySQL认为必须要执行查询的行数,在innodb引擎的表中,是一个估计值,可能并不总是准确的。⑧
filtered
:表示返回结果的行数占需读取行数的百分比,filtered 的值越大越好。
6.索引使用
1.最左前缀法则
如果索引了多列(
联合索引
),要遵守最左前缀法则。最左前缀法则指的是查询从索引的最左列开始,并且
不跳过索引中的列
。如果
跳跃某一列,索引将部分失效
(后面的字段索引失效)。
2.范围查询
联合索引中,出现范围查询
(>,<)
,范围查询右侧的列索引失效
3.索引列运算
不要在索引列上进行运算操作,
索引将失效
。
4.字符串不加引号
字符串类型字段使用时,
不加引号,索引将失效
。
5.模糊查询
如果仅仅是尾部模糊匹配,索引不会失效。
如果是头部模糊匹配,索引失效
。
6.or连接的条件
用or分割开的条件,如果or
前的条件中的列有索引,而后面的列中没有索引
,那么涉及的索引都不会被用到。
7.数据分布影响
如果MySQL评估使用索引比全表更慢,则不使用索引。
8.SQL提示
SQL提示,是优化数据库的一个重要手段,简单来说,就是在SQL语句中加入一些人为的提示来达到优化操作的目的。
9.覆盖索引
尽量使用覆盖索引(查询使用了索引,并且需要返回的列,在该索引中已经全部能够找到),
减少select *
。
在查询explain计划中的extra字段时:
①
using index condition
:查找使用了索引,但是需要回表查询
数据,所以性能更差。②
using where; using index
:查找使用了索引,但是需要的数据都在索引列中能找到,所以不需要回表查询数据。
10.前缀索引
当字段类型为字符串(varchar,text等)时,有时候需要索引
很长的字符串
,这会让索引变得很大,查询时,浪费大量的磁盘lO,影响查询效率。此时可以只将字符串的
一部分前缀
,建立索引,这样可以大大节约索引空间,从而提高索引效率。
1.创建语法
sql
create index idx_xxoxx on table_name(column(n));
2.前缀长度
可以根据索引的
选择性
来决定,而选择性是指不重复的索引值(基数)和数据表的记录总数的比值
,索引选择性越高则查询效率越高,唯一索引的选择性是1,这是最好的索引选择性,性能也是最好的。
11.单列索引与联合索引
单列索引:即一个索引只包含单个列。
联合索引:即一个索引包含了多个列。
在业务场景中,如果存在多个查询条件,考虑针对于查询字段建立索引时,建议
建立联合索引,而非单列索引
。多条件联合查询时,
MySQL优化器会评估哪个字段的索引效率更高
,会选择该索引完成本次查询。
7.索引设计原则
1.针对于
数据量较大
,且查询比较频繁
的表建立索引。2.针对于常作为
查询条件(where)、排序(order by)、分组(group by)
操作的字段建立索引。3.尽量选择
区分度高
的列作为索引,尽量建立唯一索引,区分度越高,使用索引的效率越高。4.如果是字符串类型的字段,字段的长度较长,可以针对于字段的特点,建立
前缀索引
。5、
尽量使用联合索引
,减少单列索引,查询时,联合索引很多时候可以覆盖索引,节省存储空间,避免回表,提高查询效率。6.要
控制索引的数量
,索引并不是多多益善,索引越多,维护索引结构的代价也就越大,会影响增删改的效率。7.如果索引列不能存储NULL值,请在
创建表时使用NOTNULL约束
它。当优化器知道每列是否包含NULL值时,它可以更好地确定哪个索引最有效地用于查询。