07 索引

news2024/12/23 16:00:57

1.索引 概述

1. 简介

索引是一种帮助数据库高效获取数据数据结构;通过索引可以快速获取到符合条件的数据的内存地址,避免全表扫描

2. 索引的优缺点

优点

  1. 可以快速地检索数据,降低数据IO成本
  2. 通过索引可以对数据进行排序,降低数据排序时的cpu成本

缺点

  1. 索引也是需要占据空间的
  2. 索引提高了查询的效率,但是insert、update、delete的时候需要同时维护索引,降低了效率

2. 索引结构

Mysql的索引是在引擎层实现的,不同的存储引擎支持的索引类型也不同

介绍InnodbMyISAMMEMORY
b+Tree索引最常见的索引结构,大部分引擎都支持该索引支持支持支持
Hash索引底层使用Hash表实现,仅支持等值查询,不支持范围查询-不支持支持
R-Tree索引空间引擎,主要用于地理空间数据类型,使用较少-支持-
Full-text索引全文索引,通过建立倒排索引,快速匹配文档,类似于ES;,它的出现是为了解决WHERE name LIKE “%word%"这类针对文本的模糊查询效率较低的问题支持(5.6开始)支持-

思考:为什么Innodb引擎使用B+树数据结构作为索引

  1. 相比较二叉树,解决了顺序插入或大数据量下层级过深导致查询效率慢的问题
  2. 相比较B树,由于B树的根节点和叶子节点都存放有数据,占用空间过高,层数增加;B+树只有叶子节点才存放数据,非节点存放的是键值和指针
  3. 相比较hash索引……

思考:一颗B+树最多存放多少条数据

以二阶树为例:

  1. B+树中最小存储单元为页,每一个节点都在一个页中;

  2. 已知页的大小为16k,即16*1024=16384字节

  3. 非叶子节点只存放key和指针;若key为bigint,占用大小为8字节;指针在mysql中默认6字节;加在一起共14字节;

  4. 那么非叶子节点一共可以存储16384/14=1170个指针,指向1170个叶子节点;

  5. 假设一条记录大小为1k(实践中也确实如此),那么一个叶子节点大约可以存放16条数据;

所以一个二阶树大约可以存放1170*16=18720行记录,同理,一个三阶树大约可以存放1170\*1170\*16=21902400

思考:使用Hash索引时如果出现Hash冲突会怎样

Hash索引的结构:假设对emp表的name列创建索引

  1. 计算出每一行的Hash值;
  2. 通过Hash算法,计算出name的hash值,映射到对应的插槽上,并将行的hash值带过去(行的hash值可以当作内存地址指针理解,实际上并不是);
  3. 如果两个name计算出的hash值相同,那么就会发生hash冲突,产生链表,类似Java中的HashMap

附上二叉树、B树、B+树结构图片;B树和B+树记住是满阶向上分裂

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

3. 索引分类

1. 根据功能划分

根据索引的功能可以分为:主键索引、唯一索引、普通索引、全文索引

含义特点关键字
主键索引针对表中主键创建的索引默认自动创建,只能有一个PRIMARY
唯一索引避免表中某列数据重复在添加唯一约束时会被创建,可以有多个UNIQUE
普通索引快速定位查找数据可以有多个
全文索引全文索引查找的是文本中的关键词,而不是比较索引中的值可以有多个FULLTEXT

2. 根据存储形式划分

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

含义特点
聚集索引将数据存储与索引放到了一起,索引结构的叶子节点保存了行数据必须有,而且只有一个
二级索引将数据存储和索引分开,叶子节点不保存行数据,只保存了对应的主键可以存在多个;也称为非聚集索引、辅助索引

聚集索引选取规则:

  1. 如果存在主键,主键索引就是聚集索引
  2. 如果没有主键,将使用第一个唯一索引作为聚集索引
  3. 如果没有主键,也没有聚集索引,那么InnoDB将会自动生成一个rowid作为隐藏的聚集索引

由于聚集索引中存放着完整的行数据,所以只需要通过一次查询索引即可获取数据;而二级索引中只存放了对应的主键,所以必须要先查到对应的主键,再通过聚集索引去查询,需要进行两次,这个过程称为回表查询

回表查询示意图

在这里插入图片描述

在这里插入图片描述

4. 语法

# 查看该表的索引
show index from table_name;
# 创建索引
create [unique|fulltext] index index_name on table_name(col1, ...);
# 删除索引
drop index index_name on table_name;

# 示例
show index from tb_user;
create unique index test_unique_index on tb_user(id);
create unique index test_unique_index2 on tb_user(id, name);
create index test_common_index on tb_user(id);
drop index test_common_index on tb_user;

5. 使用工具进行性能分析

1. 查看sql执行频率

可以查看当前数据库的增删改查执行次数,如果当前数据库查询为主,则可以进行优化

# 查看(全局/当前窗口)状态
show [global|session] status;
# 查看sql执行次数相关状态
show global like 'Com_______';

2. 使用慢查询日志

慢查询日志默认为关闭

该配置位于配置文件my.cnf中;下面是关于该项配置的命令

# 查询慢查询日志记录是否打开;结果为ON即为打开
show variables like 'show_query_log';
# 查看慢查询时长,默认为10s,达到10s即为慢日志会被记录下来
show variables like 'long_query_time';
# 编辑配置文件,设置show_query_log=ON,设置long_query_time=10
vi /etc/my.cnf
# 编辑完后进行重启
systemctl restart mysqld
# 重启完后慢查询将会被记录到/var/lib/mysql/localhost-slow.log日志文件中

在这里插入图片描述

3. 使用profile查看sql执行概况

profile工具默认关闭,通过have_profiling参数可以看到当前mysql是否支持profile操作;可以通过set profiling = 1开启

# 查看是否支持profile操作
select @@have_profiling;
# 查看profiling是否开启
show variables like 'profiling';
# 设置profiling为开启状态
set [global|session] profiling=1;

# 查看执行概况,返回多个sql的query_id和执行用时
show profiles;
# 查看单个sql的执行各阶段用时详情
show profile for query query_id;
# 查看单个sql的执行各阶段用时详情和cpu占用
show profile cpu for query query_id

在这里插入图片描述

在这里插入图片描述

4. 查看explain执行计划(最重要)

可以使用explain或者desc命令获取MySQL如何执行select语句的执行计划

# 查看后面的select语句执行计划
explain select 字段列表 from 数据源 where 条件;
# 同上
desc select 字段列表 from 数据源 where 条件;

explain执行计划中各字段含义:

  1. id:执行查询的序列号,表示查询中执行select子句或者是操作表的顺序;id相同,执行顺序从上往下,id不同,数值越大的越先执行
  2. select_type:表示查询的类型;常见的取值范围有SIMPLE(简单查询即不使用连接或者子查询)、PRIMARY(主查询即外层的查询)、UNION(UNION中的第二个或者后面的查询语句)、SUBQUERY(select/where之后包含了子查询);
  3. partitions:使用到的分区
  4. type:表示连接类型,性能从好到差依次为:NULL、system、const、eq_ref、ref、range、index、all;通常const表示使用了主键或者唯一索引,只有不查表的时候才会是NULL,system通常是查询系统表,ref表示使用了普通索引,all表示全表扫描
  5. possible_key:可能用到的索引,一个或者多个
  6. Key:实际用到的索引,如果为NULL表示没有用到索引
  7. Key_len:表示索引中使用的字节数;该值为索引字段最大可能长度,并非实际使用长度,在不损失精度的情况下,该值越小越好
  8. ref:指引用的东西,可以有多个,即某个表“=”号后的东西;如果是=别的表的某一列则是表名.列名,如果是一个常量则是CONST
  9. rows:MySQL认为必须要执行查询的行数;在innodb引擎中这是一个估计值,可能不总是准确
  10. filtered:表示返回结果的行数占所需要读取的行数的百分比,filtered的值越大越好

查看执行计划

在这里插入图片描述

6. 索引的使用规则

1. 左侧原则(最左前缀法则)

如果是联合索引,则需要遵守左侧原则;查询从索引的最左列开始,并且不能跳过索引中的列,如果跳过索引中的列,那么跳过的列后的列将会失效(部分失效)

  1. 如果查询条件不包含最左侧的索引列,那么索引会完全失效(因为没有最左侧的列无法判断其余的列在索引中的位置,最左侧的列在索引中排序优先级最高)
  2. 如果查询条件包含最左侧的索引列,但是跳过了中间列,那么中间列后的索引将会失效(称为索引部分失效)

2. 索引的失效情况

  1. ‘>‘和’<‘会导致范围查询右侧的列索引失效,如果业务允许,尽量使用’>=‘和’<=’
  2. 不要在索引列上进行运算操作,否则索引将失效
  3. 字符串类型的列,在查询时如果**不加’'**将会导致索引失效
  4. or查询的时候,如果or前的条件有索引,or后的列没有索引,将会导致涉及的索引都不会被用到

3. 数据分布的影响

如果MySQL评估使用索引比全表扫描更慢,那么则不使用索引

如果根据索引查询到的结果较多(例如占记录总数的一半以上),那么将不会使用索引,直接全表扫描

例如一个表中的某个索引列大多数为null,那么根据索引列查询is not null的时候,索引依旧会生效;反之如果查询is null的时候会失效,因为大多数都为null不如直接全表扫描

4. 索引提示

即通过sql语法,提示MySQL使用或者不使用索引,或者强制MySQL使用某个索引来达到优化的目的

# 提示使用某个索引;有可能不听你的
select * use index(index_name) from table_name;
# 不使用某个索引
select * ignore index(index_name) from table_name;
# 强制使用某个索引
select * force index(index_name) from table_name;

5. 覆盖索引

如果查询的列中在联合索引中都能够找到,不需要进行回表查询,那么就称之为覆盖索引

所以,使用select * 会导致回表查询,尽量避免使用回表查询

对于查询场景较为复杂的表,我们尽量使用联合索引,形成覆盖索引,避免回表查询

explain中关于extra知识点:

  1. using index condition:查找使用了索引,但是需要回表查询补全需要查找的列
  2. using where, using index:查找的列在索引中都能够找到,不需要徽标查询

思考:

一张表有四个字段:id、name、password、status,那么如何建立索引才能增加下面SQL的执行效率?

select id, name, password from user where name = ‘赵四’;

针对name和password建立联合索引,key中包含name和password,挂载的有id,形成覆盖索引,避免了回表查询

覆盖索引示意图

在这里插入图片描述

6. 前缀索引

对于一些字符串类型的列,如果列的长度较长,那么对该列建立索引所耗费的磁盘空间较大,且由于单个key较大导致树的层数增加降低查找的效率;我们可以使用前缀索引来增加效率

# 建立前缀索引,截取列的前n位作为前缀索引的key
create index ids_xxx on tablename(column_name(n));

截取的n根据索引的选择性决定,选择性指的是不重复的索引数量(基数)和表总的记录数的比值;选择性越接近1表示重复的索引key越少,效率越高;在选择性相同的情况下,n越小越好(节省空间)

# 计算选择性,不截取email
select count(distinct email)/ count(*) from users;
# 计算选择性,截取前5位作为索引的key
select count(distinct substring(eamil, 1, 5)) from users;

前缀索引的查询流程

在这里插入图片描述

7. 索引的设计原则

  1. 针对数据量较大,且多为DQL操作的表建立索引

    DML操作时也需要维护索引

  2. 针对经常作为查询条件(where)、排序(order by)、分组(group by)的列建立索引

  3. 尽量选择区分度较高的列作为索引,区分度越高索引的效率越高;尽量建立唯一索引

    例如身份证号和性别,身份证号更适合作为索引

  4. 如果字符串类型的字段长度较长,可以使用前缀索引

    否则索引太冗余并且单个key占用内存太大增加树的高度,降低效率

  5. 尽量使用联合索引,减少单列索引

    如果联合索引设计的较好那么很多时候可以覆盖索引,避免回表查询

  6. 要控制索引的数量,并不是多多益善

    首先索引也需要占用磁盘的空间,其次DML操作也需要维护索引

  7. 如果索引列不能存储null值尽量在创建表时使用not null约束

    这样子便于sql优化器知道每列是否存在null值,便于选择索引进行最有效的查询

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/32318.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

jenkins 共用宿主机中的docker自动化部署

目录 第一节 jenkins 共用宿主机中的docker自动化部署 1.docker命令安装启动jenkins 2.查询jenkins内是否可以执行宿主机中的docker 第二节.jenkins 配置自动化部署 1.界面配置 1.配置mave 2.配置gitee 第三节 创建springboot多模块项目 1.相关配置 1.pom 2.编写docke…

【面试题】作用域和闭包

1. 作用域 作用域是指变量的合法使用范围。 例如下图中&#xff0c;函数fn3内定义的变量a3&#xff0c;无法在函数fn3以外的区域使用。 作用域分为全局作用域&#xff0c;函数作用域&#xff0c;块级作用域&#xff08;ES6新增&#xff09; 全局作用域&#xff1a;变量没有受…

HTML+CSS+JS个人网页设计期末课程大作业 web前端开发技术 web课程设计 网页规划与设计

&#x1f389;精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

MYSQL索引数据结构----B+树

索引数据结构的考量 我们在考虑数据结构的时候&#xff0c;应该首先要知道数据存放在哪里&#xff1f; 而MYSQL的数据是持久化的&#xff0c;所以其数据&#xff08;数据记录索引&#xff09;应该是保存在磁盘里面的。因此当我们要查询某条数据记录时&#xff0c;就会先从磁盘…

[附源码]计算机毕业设计JAVA某城市参军和退役军人信息管理系统

[附源码]计算机毕业设计JAVA某城市参军和退役军人信息管理系统 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff…

一文理解Linux的基本指令(三分钟学会Linux基本指令)

前沿&#xff1a; 本文小马将把Linux一般比较常见的指令给大家一一列举出来&#xff0c;为了大家忘记某些指令后&#xff0c;可以方便查询记忆&#xff0c;再次小马建议&#xff0c;Linux指令并不需要去特别花时间专门记忆&#xff0c;只需要多进行操作实现就行&#xff01; &a…

算法图解学习3 选择排序

random recording 随心记录 What seems to us as bitter trials are often blessings in disguise. 看起来对我们痛苦的试炼&#xff0c;常常是伪装起来的好运。 选择排序 内存工作原理 背景引入 假设你去看演出&#xff0c;需要将东西寄存。寄存处有一个柜子&#xff0c;柜子…

Go | 函数注意事项

细节汇总 函数的形参列表可以是多个&#xff0c;返回值列表也可以是多个形参列表和返回值列表的数据类型&#xff0c;可以是值类型、也可以是引用类型函数的命名遵循标识符命名规范&#xff0c;首字母不能是数字&#xff0c;首字母大写表示该函数可以被本包文件和其它文件使用…

在线就能设计电商主图的智能平台工具

商品要上新要如何设计新品主图&#xff1f;想设计简约分的主图素材在哪&#xff1f;下面小编教你使用这个在线工具乔拓云&#xff0c;工具内包含了设计主图用到的所有工具&#xff0c;还有海量的电商模板以及免扣素材&#xff0c;都是可以直接使用到主图设计中&#xff0c;不需…

Linux中线程的介绍

目录 一.线程概念 1.什么是线程 二.Linux进程与线程 三.pthread库 3.1线程创建 3.2线程等待 3.2线程终止 3.4分离线程 四.线程ID及进程地址空间布局 一.线程概念 1.什么是线程 1.在一个程序里的一个执行路线就叫做线程&#xff08;thread&#xff09;。更准确的定义是&…

2022亚太杯建模B题思路 : 高速列车的优化设计 小美赛数学建模 B题思路

1 B题&#xff1a;高速列车的优化设计 2022年4月12日&#xff0c;中国高铁复兴CR450多机组成功实现单列列车速度435 km/h&#xff0c;相对速度870 km/h&#xff0c;创造了高铁多机组列车穿越明线和隧道速度的世界纪录。新一代标准动车组“复兴”是中国自主研发的具有全知识产权…

外贸线上推广引流的技巧

外贸网站建成后&#xff0c;很多外贸企业通常会面临一个重要的问题。网站装修和产品布局都很漂亮&#xff0c;但是流量很小。由此可见&#xff0c;外贸网站的引流推广是非常重要的。接下来&#xff0c;米贸搜给大家分享一些外贸网站引流推广的技巧&#xff0c;让网站快速获得流…

浙里办微信小程序上架

一、概述 本指南旨在为“浙里办”单点登录组件提供接入指南&#xff0c;“浙里办”单点登陆组件&#xff0c;上架在IRS&#xff0c;为上架在IRS的应用&#xff0c;提供统一的单点登录解决方案&#xff0c;现阶段仅支持微信端的接入。 二、服务创建 IRS 应用管理员在 IRS 应用…

Kali系统MSF模块暴力破解MySQL弱口令漏洞

一、实验环境 1.攻击方&#xff1a; 攻击环境使用KALI系统&#xff08;使用虚拟机搭建&#xff09;的Metasploit模块&#xff0c;msfconsole是metasploit中的一个工具&#xff0c;它集成了很多漏洞的利用的脚本&#xff0c;并且使用起来很简单的网络安全工具。 这里要特别强…

代码随想录64——额外题目【哈希表、字符串】:205同构字符串、1002查找常用字符、925长键按入、844比较含退格的字符串

文章目录1.205同构字符串1.1.题目1.2.解答2.1002查找常用字符2.1.题目2.2.解答3.925长键按入3.1.题目3.2.解答4.844比较含退格的字符串4.1.题目4.2.解答4.2.1.使用栈4.2.2.从后往前双指针1.205同构字符串 参考&#xff1a;代码随想录&#xff0c;205同构字符串&#xff1b;力扣…

MySQL数据库的索引

文章目录一、索引是什么&#xff1f;索引的作用二、索引的使用查看索引创建索引删除索引三、索引的底层一、索引是什么&#xff1f; 索引是一种特殊的文件&#xff0c;包含着对数据表里所有记录的引用指针。可以对表中的一列或多列创建索引&#xff0c;并指定索引的类型&#…

[附源码]java毕业设计医疗预约系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

SQL注入原理、过程、防御方案、RASP概念

一、sql注入原理 SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的语句上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息…

第1关:Hive的安装与配置

为了完成本关任务&#xff0c;你需要掌握&#xff1a; 1.Hive的基本安装&#xff1b; 2.Mysql的安装与设置&#xff1b; 3.Hive 的配置。 注意&#xff1a;本关实训Hive的安装与配置建立在Hadoop已安装配置好的情况下。 Hive 的基本安装 从 官网 下载Hive二进制包&#xf…

优维科技CTO黎明访谈实录:“大场景+小算法”构建AiOps运维技术哲学

智能运维、自动化运维发展到现在&#xff0c;已经有将近7成的IT管理者学会利用大数据、人工智能产品及解决方案赋能团队&#xff0c;在生产效率、适应性和决策能力等层面实现了切实有效的正向转型。 今天的中国企业&#xff0c;已经在云端新基建、数字化转型的浪潮中实现降本增…