MySQL中的索引

目录

目录

目录

索引概述-->

介绍--->

优缺点--->

索引结构-->

​编辑

存储引擎支持情况--->

BTree--->

B+Tree--->

Hash--->

Hash特点--->

思考题

索引分类-->

InnoDB存储引擎中--->

聚集索引--->

二级索引--->

执行过程--->

思考题

索引语法-->

代码示范--->

SQL性能分析-->

SQL执行频率--->

慢日志查询--->

代码演示--->

profile详情--->

代码演示--->

explain执行计划-->

代码演示--->

索引使用-->

验证索引效率--->

代码示范--->

最左前缀法则--->

代码示范--->

范围查询--->

代码示范--->

索引失效情况--->

索引失效情况一--->

代码示范--->

索引失效情况二--->

代码示范--->

SQL提示--->

代码示范--->

覆盖索引&回表查询--->

代码示范--->

前缀索引--->

代码示范--->

工作流程--->

单列索引和联合索引--->

代码示范--->

联合索引查询流程

 索引设计原则--->

总结


索引概述-->

介绍--->

优缺点--->


索引结构-->

存储引擎支持情况--->

BTree--->

每当节点到5个Key时,中间值向上分裂,左边小于中间值,右边大于中间值

B+Tree--->

MySQL优化处理--->

BTree的基础上,分裂的同时将本身放在叶子节点形成链表,左边小于中间值,右边大于等于中间值

Hash--->

Hash特点--->

思考题


索引分类-->

InnoDB存储引擎中--->

聚集索引--->

此处叶子节点row存放的就是每一行的数据

二级索引--->

此处叶子节点存放id

执行过程--->

先在二级索引中,拿'Arm与Lee'比较,小于'Lee',继续找左边

与'Geek'比较,小于'Geek',继续找左边

找到'Arm'存储的id为10

此时在聚集索引中再通过id=10找到对应的行数据返回

这样的查询方式也叫回表查询

思考题

解答-->

select * from user where id = 10;效率高

原因是直接进行聚集索引查询,省去了二级索引的查询

高度每+1,key = 原key * 1171 * 16


索引语法-->

代码示范--->

-- 创建数据库
CREATE DATABASE IF NOT EXISTS itcast DEFAULT CHARSET utf8mb4 ;

use itcast;

-- 准备表和数据 id为主键
CREATE TABLE tb_user(
    id int primary key auto_increment COMMENT 'id',
    name varchar(10) COMMENT '姓名',
    phone char(11) COMMENT '电话',
    email varchar(20) COMMENT '邮箱',
    profession varchar(10) COMMENT '专业',
    age int COMMENT '年龄',
    gender int COMMENT '性别',
    status int COMMENT '状态',
    createtime DATETIME COMMENT '入职时间'
) COMMENT '用户表';

INSERT INTO tb_user VALUES (1,'吕布','17799990000','lvbu666@163.com','软件工程',23,1,6,'2001-02-02 00:00:00'),
                           (2,'曹操','17799990001','caocao666@qq.com','通讯工程',33,1,6,'2001-03-05 00:00:00'),
                           (3,'赵云','17799990002','177999908139.com','英语',34,1,2,'2002-03-02 00:00:00'),
                           (4,'孙悟空','17799990003','17799990@sina.com','工程造价',54,1,0,'2001-07-02 00:00:00'),
                           (5,'花木兰','17799990004','19980729@sina.com','软件工程',23,2,1,'2001-04-22 00:00:00');

-- 需求
-- 1.name字段为姓名字段,该字段的值可能会重复,为该字段创建索引
create index idx_user_name on tb_user(name);

-- 2.phone手机号字段的值,是非空,且唯一的,为该字段创建唯一索引
create unique index idx_user_phone on tb_user(phone);

-- 3.为profession、age、status创建联合索引
create index idx_user_pro_age_sta on tb_user(profession,age,status);

-- 4.为email建立合适的索引来提高查询效率
create index idx_user_email on tb_user(email);

-- 查询索引
show index from tb_user;

结果--->


SQL性能分析-->

SQL执行频率--->

慢日志查询--->

代码演示--->

查询慢日志查询--->

使用vi编辑器配置信息--->此时状态为OFF关闭

返回后重新启动mysql服务器--->

再次查询--->此时状态为ON打开

查找存放慢日志文件的位置--->此时文件中存放的只有一些基本信息

查询1000w条数据--->出现慢查询日志

profile详情--->

使用-->

代码演示--->

启用profiling--->

进行三个查询操作--->

通过profiles操作查看每条sql的耗时基本情况--->

通过profiles操作查看sql语句各个阶段的耗时情况--->

通过profiles操作查看sql语句各个阶段cpu的使用情况--->

explain执行计划-->

explain执行计划各字段含义:

代码演示--->

查看sql语句的执行计划--->

id值相同--->

id值不同--->


索引使用-->

验证索引效率--->

代码示范--->

创建索引前--->

创建索引--->

创建索引后--->


最左前缀法则--->

代码示范--->

从索引最左列开始,并且没跳过索引中的列--->

从索引最左列开始,并且没跳过索引中的列,不包含最后一个索引--->

只用最左列的索引--->

不包含最左列的索引,只使用后两个索引--->没调用索引,因为不符合最左前缀法则

包含最左列的所有,但不包含中间的索引,包含最后的索引--->最后的索引失效了,因为最左前缀法则跳过了某一列,后面的所有列索引都会失效

先执行age和status,最后执行最左列的索引--->全部索引生效,最左前缀法则没有规定最左列索引放的位置


范围查询--->

代码示范--->

查询最左索引和age,经过>符号后继续执行status--->不执行status索引

查询最左索引和age,经过>=符号后继续执行status--->执行全部索引

索引失效情况--->

索引失效情况一--->

代码示范--->

正常查询一段数据--->调用了所有索引

进行了函数运算并查询--->没调用任何索引

正常查询一段数据--->调用了所有索引

字符串没有用引号查询数据--->可能用到所有索引,但实际没有使用

使用尾部模糊匹配--->用到所有索引

使用头部模糊匹配--->没用到索引

索引失效情况二--->

代码示范--->

只用age和id查询--->age没索引,id有索引,结果:id索引可能用到,实际都没用到

解决--->给age添加索引

通过phone条件从第三条数据开始查询--->使用了所有索引

通过phone条件从第一条数据开始查询--->没有使用索引:只要大部分数据满足要求,就走全表扫描,不走索引

类上图

SQL提示--->

代码示范--->

在已经创建联合索引的情况下,再创建单列索引--->

在profession同时有联合索引和单列索引的情况下执行--->MySQL优化器自动选择了联合索引

使用use建议MySQL使用该单列索引执行--->使用了单列索引

使用ignore让MySQL忽略单列索引执行--->使用了联合索引

使用force让MySQL强制使用单列索引执行--->使用了单列索引

覆盖索引&回表查询--->

能够在聚集索引或二级索引中直接找到select要的所有信息就是覆盖索引

需要回表,先通过二级索引查到主键,再去聚集索引查找select字段的就是回表查询

代码示范--->

使用联合索引查询一段数据--->

select指定查询id、profession和id、profession、age以及id、profession、age、status其他同上--->执行计划都相同

代码同上(select多指定一个name)--->Extra由Using where, Using index变为Using index condition(前者效率更高)

前缀索引--->

代码示范--->

获取email的索引选择性--->

截取email字符串1-9和1-7的索引选择性--->1-9为1不会重复,1-8为0.8会重复,1-5也为0.8会重复

结果:如果对选择性要求很高,就使用1-9选择性为1,如果要平衡索引体积和选择性就选1-5选择性为0.8

创建email前缀索引,取前五个--->

通过前缀索引查询字段--->

工作流程--->

截取email前五个字段,lvbu5,在辅助索引中找到lvbu6对应的值-->回表查询-->找到id对应的row,再拿row和完整字符串lvbu666@163.com比较,相同则返回,不同则回到辅助索引中往链表后一个查询,然后继续回表比较

单列索引和联合索引--->

代码示范--->

根据两个字段查询一段数据--->只走了一个字段

创建一个phone和name的唯一联合索引,再次进行查询--->只用到了phone索引

使用use建议使用联合索引再次进行查询--->

结果:NULL表示要用到回表查询,Using index效率更高

联合索引查询流程

先根据phone查询,如果phone相同再根据name查询


 索引设计原则--->


总结

  • 33
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值