MySQL高级--索引

索引

笔记来源

1.索引概述

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

优点缺点
提高数据检索效率,降低IO成本索引需要占有一定空间
通过索引列对数据进行排序,降低数据排序的成本,降低CPU的消耗降低了更新表的速度

2.索引结构

在这里插入图片描述
MySQL的索引实在存储引擎层实现的,不同的存储引擎有不同的索引结构

索引结构描述
B+Tree索引最常见的索引类型,大部分引擎都支持B+索引
Hash索引底层是Hash表实现的,只支持精确匹配,不支持范围查询和排序
R- Tree(空间索引)空间索引是MyISAM引擎的一个特殊索引类型,主要用于地理空间数据类型
Full-text(全文索引)是一种通过建立倒排索引,快速匹配文档的方式,类似于Lucene,Solr, ES
索引InnoDBMyISAMMemory
B+索引支持支持支持
Hash索引不支持不支持支持
R-tree索引不支持支持不支持
Full-text5.6之后支持支持不支持

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

在这里插入图片描述
B-Tree展示网站

2.2 B+Tree

在这里插入图片描述
B+Tree展示网站
和B-Tree的区别:
1.数据都存在叶子节点
2.叶子节点形成一个单向链表

Mysql
优化:叶子节点是双向链表
在这里插入图片描述

2.3 Hash索引

经过hash算法将键值换成新的hash值,映射到对应的槽位上,然后存储在hash表中
在这里插入图片描述
特点:
1.Hash索引只能用于对等比较(=,in),不支持范围查询(between,>,<,…)
2.无法利用索引完成排序操作
3.查询效率高,通常只需要一次检索就可以了,效率通常要高于B+Tree索引

为什么InnoDB存储引擎使用B+Tree索引结构?
1.相对于二叉树,层级更少,搜索效率高
2.对于B树,无论是叶子节点非叶子节点都需要存储数据,这样导致一页中可以存储的键减少,指针数减少,要想保存大量的数据,只能增加树的高度,降低了性能。
3.相对于Hash索引,B+Tree支持范围以及排序操作

3.索引分类

分类含义特点关键字
主键索引针对表中主键所创建的索引默认自动创建,只能有一个PRIMARY
唯一索引避免同一个表中某数据列中的值重复可以有多个UNIQUE
常规索引快速定位特定数据可以有多个
全文索引全文索引查找文本中的关键字,而不是比较索引中的值可以有多个FULLTEXT

根据索引的存储形式分类

分类含义特点
聚集索引(Clustered Index)将数据和索引放在一起,索引结构的叶子节点保存了行数据必须有,只能有一个
二级索引(Secondary index)将数据和索引分开存储,索引结构的叶子节点关联的是对应的主键可以存在多个

聚集索引选取规则

  • 如果存在索引,主键索引就是聚集索引
  • 如果不存在主键,将使用第一个唯一索引(UNIQUE)作为聚集索引
  • 如果没有主键和唯一索引,则InnoDB会自动生成一个rowid作为隐藏的聚集索引

回表查询
在这里插入图片描述

4.索引语法

4.1 创建索引

CREATE [UNIQUE|FULLTEXT] INDEX index_name ON table_name (index_col_name,...);

4.2 查看索引

SHOW INDEX FROM table_name;

4.3 删除索引

DROP INDEX index_name ON table_name;

5.SQL性能分析

5.1 SQL执行频率

MySQL客户端连接成功后,通过命令可以提供服务器状态信息。通过以下指令,可以查看当前数据库INSERT、UPDATE、DELETE、SELECT执行频率

SHOW GLOBAL STATUS LIKE 'Com_______';

在这里插入图片描述

5.2 慢查询日志

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

show variables like 'slow_query_log';

在这里插入图片描述
开启需要在MySQL的配置文件(/etc/my.cnf)中配置如下信息:

# 开启MySQL慢查询日志的开关
slow_query_log=1
# 设置慢日志的时间为2秒,SQL语句执行时间超过2秒,就会被视为慢查询,记录慢查询日志
long_query_time=2

当设置开启慢查询日志后,在 /var/lib/mysql/ 文件夹下会生成一个 ****-slow.log 的日志文件(****取决于你服务器)在这里插入图片描述

5.3 profile

show profiles;

show profiles 能够在做优化时帮助我们了解时间都耗费到哪了。
have_profiling 参数,能够看到当前MySQL是否支持 profile操作

select @@have_profiling;

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

set profiling = 1;

在这里插入图片描述
查询所有语句耗费的时间

show profiles;

在这里插入图片描述
查询具体语句的耗时

show profiles for query 1;

在这里插入图片描述

5.4 explain执行计划

explain + sql语句 显示sql的执行计划

explain 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_keys
    表中可能用到的索引
  • key
    用到的索引
  • key_len
    索引的长度
  • rows
    MySQL认为必须要执行查询的行数,在innoDB引擎中,是一个预估值,可能并不总是准确的
  • filtered
    表示返回结果的行数站总读取行数的百分比,filtered的值越大越好

6.索引的使用

6.1 最左前缀法则

如果索引了多列(联合索引),要遵守最左前缀法则。最左前缀法则指的是查询从索引的最左列开始,并且不跳过索引中的列
如果跳跃某一列,索引将部分失效(后面的索引失效)
在这里插入图片描述
这里有一个联合索引,分别是由real_name, phone, email组成,我们看下面几个sql
(1)最左前缀法则

select * from sys_user where real_name = 'xzx' and phone = '19826520135' and email = '1493012739@qq.com';

在这里插入图片描述
这个SQL走了联合索引,索引长度为777

(2)最左前缀法则

select * from sys_user where real_name = 'xzx' and phone = '19826520135';

在这里插入图片描述
因为没有跳过某一列,依然遵守最左匹配法则,用到了联合索引,索引长度变成518,长度减少

(3)最左前缀法则

select * from sys_user where real_name = 'xzx';

在这里插入图片描述
依然遵守最左匹配法则,用到了联合索引,索引长度变成259,长度依旧减少

(4)最左前缀法则

select * from sys_user where phone = '19826520135' and email = '1493012739@qq.com';

在这里插入图片描述
最左边的列没有出现,不满足最左匹配法则,全表扫描

(5)最左前缀法则

select * from sys_user where email = '1493012739@qq.com';

在这里插入图片描述
不满足最左匹配法则,全表扫描

(6)最左前缀法则

select * from sys_user where real_name = 'xzx' and email = '1493012739@qq.com';

在这里插入图片描述
走索引,但不完全,索引长度259, 只有real_name走索引,因为phone没有出现,所以email失效

(7)索引跟顺序的关系

select * from sys_user where phone = '19826520135' and email = '1493012739@qq.com' and real_name = 'xzx';

在这里插入图片描述
索引全部生效,跟创建顺序有关,跟查询顺序无关

(8)> 和 >= 的区别

select * from sys_user where real_name = 'xzx' and phone = '19826520135' and email = '1493012739@qq.com';
select * from sys_user where real_name = 'xzx' and phone >= '19826520135' and email = '1493012739@qq.com';

在这里插入图片描述
两个sql对比,>范围查询会使后面的索引失效,>=则不会

(9)对索引字段进行函数运算
在这里插入图片描述
这里对phone有一个单列索引

select * from sys_user where substring(phone, 10, 2) = '35';

对phone进行截取函数
在这里插入图片描述
未命中索引,函数运算不触发索引

(9)字符串不加单引号

select * from sys_user where phone = '35';

在这里插入图片描述
索引失效,字符串类型不加单引号

(10)%模糊搜索

select * from sys_user where phone like '%35';
select * from sys_user where phone like '35%';

在这里插入图片描述
前面加%索引失效,后面加%索引命中

(11)or连接的条件
用 or 分割开的条件,如果or前的条件中的列没有索引,那么设计的索引都不会用到

select * from sys_user where id = '1' or phone = '19826520135';
select * from sys_user where id = '1' or email ='1493012739@qq.com';

在这里插入图片描述
id主键索引,phone单列索引,email没有索引
要么都有索引,都生效,要么都没有,有一个都不生效

(12)mysql自己评估
有时候失效,mysql认为没必要用索引

7.SQL提示

SQL提示,是优化数据库的一个重要手段,简单来说,就是在SQL语句中加入一些人为的提示来达到优化操作的目的。
说白了,就是给sql提示
use index 用哪个索引 (只是建议mysql,mysql可以不听)

select * from sys_user use index(index_real) where real_name = 'xzx';

在这里插入图片描述

ignore index 不用哪个索引

select * from sys_user ignore index(index_real_phone_email) where real_name = 'xzx';

在这里插入图片描述

force index 必须用哪个索引

select * from sys_user force index(index_real) where real_name = 'xzx';

在这里插入图片描述

8.覆盖索引

尽量使用覆盖索引(查询使用了索引,并且需要返回的列,在该索引中已经全部能找到),减少select *
在这里插入图片描述

9.前缀索引

当字段类型为字符串(varchar,text等)时,有时候需要索引很长的字符串,这会让索引变得很大,查询时,浪费大量的磁盘IO,
影响查询效率。此时可以只将字符串的一部分前缀,建立索引,这样可以大大节约索引空间,从而提高索引效率。
语法

create index 索引名称 on 表名(列名(长度))

前缀长度
可以根据索引的选择性来决定,而选择性是指不重复的索引值(基数)和数据表的记录总数的比值,索引选择性越高则查询效率越高,唯一索引的选择性是1,这是最好的索引选择性,性能也是最好的。

select count(distinct substring(计算字段,截取点,截取长度))/count(*) from 表名;

10.索引设计原则

在这里插入图片描述

11.面试题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值