MySQL数据库进阶-索引

索引

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

优缺点

优点:

  • 提高数据检索效率,降低数据库的IO成本

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

缺点:

  • 索引列也是要占用空间的

  • 索引大大提高了查询效率,但降低了更新的速度,比如 INSERT、UPDATE、DELETE

索引结构

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

B-Tree

二叉树

二叉树的缺点可以用红黑树来解决:

红黑树

红黑树也存在大数据量情况下,层级较深,检索速度慢的问题。

为了解决上述问题,可以使用 B-Tree 结构。 B-Tree (多路平衡查找树) 以一棵最大度数(max-degree,指一个节点的子节点个数)为5(5阶)的 b-tree 为例(每个节点最多存储4个key,5个指针)

B-Tree结构

演示地址:B-Tree Visualization

B+Tree

结构图:

B+Tree结构图

演示地址:B+ Tree Visualization

与 B-Tree 的区别:

  • 所有的数据都会出现在叶子节点

  • 叶子节点形成一个单向链表

MySQL 索引数据结构对经典的 B+Tree 进行了优化。在原 B+Tree 的基础上,增加一个指向相邻叶子节点的链表指针,就形成了带有顺序指针的 B+Tree,提高区间访问的性能。

MySQL B+Tree 结构图

Hash

哈希索引就是采用一定的hash算法,将键值换算成新的hash值,映射到对应的槽位上,然后存储在hash表中。 如果两个(或多个)键值,映射到一个相同的槽位上,他们就产生了hash冲突(也称为hash碰撞),可以通过链表来解决。

Hash索引原理图

特点:

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

  • 无法利用索引完成排序操作

  • 查询效率高,通常只需要一次检索就可以了,效率通常要高于 B+Tree 索引

存储引擎支持:

  • Memory

  • InnoDB: 具有自适应hash功能,hash索引是存储引擎根据 B+Tree 索引在指定条件下自动构建的

 

面试题

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

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

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

  • 相对于 Hash 索引,B+Tree 支持范围匹配及排序操作

索引分类

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

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

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

演示图:

大致原理

演示图

聚集索引选取规则:

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

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

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

思考题

1. 以下 SQL 语句,哪个执行效率高?为什么?

select * from user where id = 10;
select * from user where name = 'Arm';
-- 备注:id为主键,name字段创建的有索引

答:第一条语句,因为第二条需要回表查询,相当于两个步骤。

2. InnoDB 主键索引的 B+Tree 高度为多少?

答:假设一行数据大小为1k,一页中可以存储16行这样的数据。InnoDB 的指针占用6个字节的空间,主键假设为bigint,占用字节数为8. 可得公式:n * 8 + (n + 1) * 6 = 16 * 1024,其中 8 表示 bigint 占用的字节数,n 表示当前节点存储的key的数量,(n + 1) 表示指针数量(比key多一个)。算出n约为1170。

如果树的高度为2,那么他能存储的数据量大概为:1171 * 16 = 18736; 如果树的高度为3,那么他能存储的数据量大概为:1171 * 1171 * 16 = 21939856

另外,如果有成千上万的数据,那么就要考虑分表,涉及运维篇知识。

语法

创建索引: CREATE [ UNIQUE | FULLTEXT ] INDEX index_name ON table_name (index_col_name, ...); 如果不加 CREATE 后面不加索引类型参数,则创建的是常规索引

查看索引: SHOW INDEX FROM table_name;

删除索引: DROP INDEX index_name ON table_name;

案例:

-- name字段为姓名字段,该字段的值可能会重复,为该字段创建索引
create index idx_user_name on tb_user(name);
-- phone手机号字段的值非空,且唯一,为该字段创建唯一索引
create unique index idx_user_phone on tb_user (phone);
-- 为profession, age, status创建联合索引
create index idx_user_pro_age_stat on tb_user(profession, age, status);
-- 为email建立合适的索引来提升查询效率
create index idx_user_email on tb_user(email);
​
-- 删除索引
drop index idx_user_email on tb_user;

使用规则

最左前缀法则

如果索引关联了多列(联合索引),要遵守最左前缀法则,最左前缀法则指的是查询从索引的最左列开始,并且不跳过索引中的列。 如果跳跃某一列,索引将部分失效(后面的字段索引失效)。

联合索引中,出现范围查询(<, >),范围查询右侧的列索引失效。可以用>=或者<=来规避索引失效问题。

索引失效情况

  1. 在索引列上进行运算操作,索引将失效。如:

explain select * from tb_user where substring(phone, 10, 2) = '15';
  1. 字符串类型字段使用时,不加引号,索引将失效。如:explain select * from tb_user where phone = 17799990015;,此处phone的值没有加引号

  2. 模糊查询中,如果仅仅是尾部模糊匹配,索引不会是失效;如果是头部模糊匹配,索引失效。如:explain select * from tb_user where profession like '%工程';,前后都有 % 也会失效。

  3. 用 or 分割开的条件,如果 or 其中一个条件的列没有索引,那么涉及的索引都不会被用到。

  4. 如果 MySQL 评估使用索引比全表更慢,则不使用索引。

SQL 提示

是优化数据库的一个重要手段,简单来说,就是在SQL语句中加入一些人为的提示来达到优化操作的目的。

例如,使用索引:

​explain select * from tb_user use index(idx_user_pro) where profession="软件工程";

不使用哪个索引:

explain select * from tb_user ignore index(idx_user_pro) where profession="软件工程";

必须使用哪个索引:

explain select * from tb_user force index(idx_user_pro) where profession="软件工程";

use 是建议,实际使用哪个索引 MySQL 还会自己权衡运行速度去更改,force就是无论如何都强制使用该索引。

覆盖索引&回表查询

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

explain 中 extra 字段含义:

using index condition:查找使用了索引,但是需要回表查询数据 using where;

using index;:查找使用了索引,但是需要的数据都在索引列中能找到,所以不需要回表查询

如果在聚集索引中直接能找到对应的行,则直接返回行数据,只需要一次查询,哪怕是select *;如果在辅助索引中找聚集索引,如select id, name from xxx where name='xxx';,也只需要通过辅助索引(name)查找到对应的id,返回name和name索引对应的id即可,只需要一次查询;如果是通过辅助索引查找其他字段,则需要回表查询,如select id, name, gender from xxx where name='xxx';

所以尽量不要用select *,容易出现回表查询,降低效率,除非有联合索引包含了所有字段

面试题:一张表,有四个字段(id, username, password, status),由于数据量大,需要对以下SQL语句进行优化,该如何进行才是最优方案:

select id, username, password from tb_user where username='itcast';

解:给username和password字段建立联合索引,则不需要回表查询,直接覆盖索引

前缀索引

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

语法:create index idx_xxxx on table_name(columnn(n));

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

select count(distinct email) / count(*) from tb_user;
select count(distinct substring(email, 1, 5)) / count(*) from tb_user;

show index 里面的sub_part可以看到接取的长度

单列索引&联合索引

单列索引:即一个索引只包含单个列 联合索引:即一个索引包含了多个列 在业务场景中,如果存在多个查询条件,考虑针对于查询字段建立索引时,建议建立联合索引,而非单列索引。

单列索引情况: explain select id, phone, name from tb_user where phone = '17799990010' and name = '韩信'; 这句只会用到phone索引字段

注意事项

  • 多条件联合查询时,MySQL优化器会评估哪个字段的索引效率更高,会选择该索引完成本次查询

设计原则

  1. 针对于数据量较大,且查询比较频繁的表建立索引

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

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

  4. 如果是字符串类型的字段,字段长度较长,可以针对于字段的特点,建立前缀索引

  5. 尽量使用联合索引,减少单列索引,查询时,联合索引很多时候可以覆盖索引,节省存储空间,避免回表,提高查询效率

  6. 要控制索引的数量,索引并不是多多益善,索引越多,维护索引结构的代价就越大,会影响增删改的效率

  7. 如果索引列不能存储NULL值,请在创建表时使用NOT NULL约束它。当优化器知道每列是否包含NULL值时,它可以更好地确定哪个索引最有效地用于查询

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

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

相关文章

CSS3渐变属性详解

渐变属性 线性渐变 概念&#xff1a;线性渐变&#xff0c;指的是在一条直线上进行的渐变。在线性渐变过程中&#xff0c;起始颜色会沿着一条直线按顺序过渡到结束颜色 语法&#xff1a; background:linear-gradient(渐变角度&#xff0c;开始颜色&#xff0c;结束颜色);渐变…

https配置证书

HTTPS 基本原理 https 介绍 HTTPS&#xff08;全称&#xff1a;HyperText Transfer Protocol over Secure Socket Layer&#xff09;&#xff0c;其实 HTTPS 并不是一个新鲜协议&#xff0c;Google 很早就开始启用了&#xff0c;初衷是为了保证数据安全。 国内外的大型互联网…

SQL 基础知识点

1. 数据库相关术语 数据库&#xff08;database&#xff09;&#xff1a;保存有组织的数据的容器&#xff08;通常是一个文件或一组文件&#xff09;。数据表&#xff08;table&#xff09; &#xff1a;某种特定类型数据的结构化清单。模式&#xff08;schema&#xff09;&am…

springboot 房屋租赁系统

spring boot mysql mybatis 前台后端

开心自走棋:使用 Laf 云开发支撑数百万玩家

先介绍一下开心自走棋 开心自走棋是一款剑与魔法的烧脑自走棋游戏。以著名的魔幻世界观为蓝本&#xff0c;采用了轻松可爱的画面风格&#xff0c;精致细腻的动画和特效来还原魔兽之战。 现在市面上自走棋游戏多是 PvP 玩法为主&#xff0c;而开心自走棋是以 PvE 玩法为主的&a…

C语言光速入门笔记

C语言是一门面向过程的编译型语言&#xff0c;它的运行速度极快&#xff0c;仅次于汇编语言。C语言是计算机产业的核心语言&#xff0c;操作系统、硬件驱动、关键组件、数据库等都离不开C语言&#xff1b;不学习C语言&#xff0c;就不能了解计算机底层。 目录 C语言介绍C语言特…

相机成像之图像传感器与ISP【四】

文章目录 1、图像传感器基础1.1 基础原理——光电效应1.2 基础的图像传感器设计1.3 衡量传感器效率的一个关键指标&#xff1a;光量子效率&#xff08;QE&#xff09;1.4 感光单元的响应1.5 像素的满阱容量1.6 像素尺寸和填充比例1.7 微透镜的作用1.8 光学低通滤波器简介1.9 传…

机器学习周报第27周

目录 摘要Abstract一、文献阅读 摘要 本周阅读了一篇混沌时间序列预测的论文&#xff0c;论文模型主要使用的是时间卷积网络&#xff08;Temporal Convolutional Network&#xff0c;TCN&#xff09;、LSTM以及GRU。在数据集方面除了使用现实的时间序列数据外&#xff0c;还通…

计算机毕业设计 | SpringBoot+vue农产品商城 买菜购物网站(附源码)

1&#xff0c;绪论 1.1 项目背景 随着社会发展&#xff0c;网上购物已经成为我们日常生活的一部分。但是&#xff0c;至今为止大部分电商平台都是从人们日常生活出发&#xff0c;出售都是一些日常用品比如&#xff1a;食物、服装等等&#xff0c;并未发现一个专注于菜品的电商…

路由器02_静态路由DHCP

一、静态路由 &#xff11;、静态路由特点 由管理员手工配置&#xff0c;是单向的&#xff0c;缺乏灵活性 &#xff12;、默认路由 默认路由是一种比较特殊静态路由&#xff0c;一般用于末节&#xff08;末梢&#xff09;网络&#xff0c;直接指定目标为任何地方 二、静态…

为什么 Kafka 这么快?它是如何工作的?

随着数据以指数级的速度流入企业&#xff0c;强大且高性能的消息传递系统至关重要。Apache Kafka 因其速度和可扩展性而成为热门选择&#xff0c;但究竟是什么让它如此之快&#xff1f; 在本期中&#xff0c;我们将探讨&#xff1a; Kafka 的架构及其核心组件&#xff0c;如生…

Xfs文件系统磁盘布局

目录 一&#xff0c;CentOS下Xfs文件系统的安装 二&#xff0c;准备工作 三&#xff0c;AG结构 四&#xff0c;AG超级块 五&#xff0c;AG空闲磁盘空间管理 六&#xff0c;ABTB的Btree 七&#xff0c;ABTB/ABTC的节点块管理 八&#xff0c;inode节点管理 九&#xff0…

Vue-5、el和data的两种写法

1、el 第一种写法 <!DOCTYPE html> <html lang"en" xmlns:v-model"http://www.w3.org/1999/xhtml" xmlns:v-bind"http://www.w3.org/1999/xhtml"> <head><meta charset"UTF-8"><title>el和data的两种写…

vue3中路由的使用(详细讲解)

1、路由的简介 路由(route)&#xff1a;就是根据特定的规则将数据包或请求从源地址传输到目标地址的过程。 在前端或者vue3项目中路由主要用于构建单页面应用程序&#xff08;SPA&#xff09;&#xff0c;其中所有的页面都在同一个HTML文件中加载&#xff0c;通过JavaScript动…

自监督深度学习技术

一、定义 自监督学习&#xff08;SSL&#xff09;是机器学习的一种范式&#xff0c;用于处理未标记数据以获取有用的表示&#xff0c;以帮助下游学习任务。SSL方法最显著的特点是它们不需要人类标注的标签&#xff0c;这意味着它的训练完全基于由未标记的数据样本组成的数据集…

网络通信过程的一些基础问题

客户端A在和服务器进行TCP/IP通信时&#xff0c;发送和接收数据使用的是同一个端口吗&#xff1f; 这个问题可以这样来思考&#xff1a;在客户端A与服务器B建立连接时&#xff0c;A需要指定一个端口a向服务器发送数据。当服务器接收到A的报文时&#xff0c;从报文头部解析出A的…

018、通用集合类型

Rust标准库包含了一系列非常有用的被称为集合的数据结构。大部分的数据结构都代表着某个特定的值&#xff0c;但集合却可以包含多个值。 与内置的数组与元组类型不同&#xff0c;这些集合将自己持有的数据存储在了堆上。这意味着数据的大小不需要在编译时确定&#xff0c;并且可…

WEB 3D技术 three.js 顶点交换

本文 我们来说 顶点的转换 其实就是 我们所有顶点的位置发生转变 我们整个物体的位置也会随之转变 这里 我们编写代码如下 import ./style.css import * as THREE from "three"; import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.j…

kettle的基本介绍和使用

1、 kettle概述 1.1 什么是kettle Kettle是一款开源的ETL工具&#xff0c;纯java编写&#xff0c;可以在Window、Linux、Unix上运行&#xff0c;绿色无需安装&#xff0c;数据抽取高效稳定。 1.2 Kettle核心知识点 1.2.1 Kettle工程存储方式 以XML形式存储以资源库方式存储…

【数据结构】树的遍历

树的遍历 前序遍历 前序遍历是按照根节点->左子树->右子树的顺序进行遍历 图片来源维基百科深度优先遍历&#xff08;前序遍历&#xff09;: F, B, A, D, C, E, G, I, H. 代码实现 递归 # class TreeNode: # def __init__(self, x): # self.val x # …