系列文章目录
- 第一章 C/C++语言篇
- 第二章 计算机网络篇
- 第三章 操作系统篇
- 第四章 数据库MySQL篇
- 第五章 数据库Redis篇
- 第六章 场景题/算法题
- 第七篇 常见HR问题篇
本系列专栏:点击进入 后端开发面经 关注走一波
秋招阶段,面过很多大中小厂,积攒了很多面经,都是高频问题!!!
前言:本系列文章初衷是为了整理出最全面最详细的面经,非常适用于想走后端/软件开发
的同学!近些年,越来越多的人投入互联网的浪潮,由于岗位hc有限,企业筛选门槛也随之提高。以往的简单八股问答也在不断升级,面试官开始更喜欢问为什么,会围绕八股的某一点不断深问。所以本系列文章的面经不仅仅是简单问答,而是帮你深入理解和掌握知识点,其中一些晦涩难懂的知识点,全都用案例和代码帮你彻底掌握,切记一定要理解原理,拒绝死记硬背!!!
文章目录
- 系列文章目录
- 基础篇
- 关系型数据库和非关系数据库的区别
- MySQL、MongoDB和Redis的区别
- MySQL体系结构
- InnoDB、MyISAM、Memory三种存储引擎对比
- 不同存储引擎的选择
- 数据库有哪些SQL语句分类
- DQL 执行顺序
- where 和 having 的区别
- replace into 和 insert into 的区别
- truncate 和 drop 的区别
- 各种函数介绍(字符串、数值、日期、流程)
- 介绍 MySQL 中的字段约束
- 内连接查询和外连接查询的区别
- 有哪些性能分析的语句
- 数据库的优化方法
- 介绍MySQL中的视图
- InnoDB 的行格式介绍
- varchar类型如何记录数据的真实长度
- varchar(n) 中 n 最大取值为多少
- NULL会记录在表中吗?
- 行溢出后,MySQL 是怎么处理的
- 索引篇
- 事务篇
- 锁篇
- 运维篇
基础篇
关系型数据库和非关系数据库的区别
- 关系型数据库是一种使用表格形式存储数据的数据库系统,数据通过行和列组织,并且表之间可以通过外键建立关系,常见的有MySQL、PostgreSQL和Oracle等。
- 非关系型数据库则不采用固定的表格结构,可以支持多种数据存储模型,如文档、键值、图和列族,适合处理大规模和多样化的数据,常见的有MongoDB、Redis和Cassandra等。
下面是它们的主要区别:
对比类型 | 关系型数据库 | 非关系数据库 |
---|---|---|
数据结构 | 表格形式 | 文档型(mongdb)、键值型(redis) |
事务支持 | 支持ACID事务,保证强一致性 | 最终一致性,不是严格的事务管理 |
灵活性 | 数据结构固定,表结构的变更昂贵复杂 | 数据结构灵活存储,形式多样 |
查询语句 | SQL语句 | 类 SQL(mongdb)、命令行操作(redis) |
适用场景 | 适合需要复杂查询和事务支持的应用 | 适合需要高可扩展性、灵活数据模型和快速读写的应用 |
MySQL、MongoDB和Redis的区别
数据库 | MySQL | MongoDB | Redis |
---|---|---|---|
数据模型 | 关系型数据库 | 非关系型数据库 | 非关系型数据库 |
存储数据类型 | 二维表结构 | BSON格式文档存储 | 键值对 |
数据结构 | 数值、时间、字符串等常用类型 | 除常用类型,还支持数组和字典 | 字符串、列表、集合、哈希等 |
存储方式 | 不同引擎有不同的存储 | 基于内存,热数据存放物理内存,高速读写 | 完全基于内存,持久化可选 |
查询方式 | SQL语句 | 基于文档的查询语言 | 基于键的简单操作 |
多表联查 | 一对多、多对多情况下,使用外键,JOIN查询 | 嵌套或者通过ID引用其他集合 | 不支持联查 |
事务支持 | 支持 | 仅支持单文档事务 | 支持简单事务 |
数据一致性 | 强一致性,保证在所有副本上的数据是一致的 | 会牺牲一致性来获得更好的性能,采用最终一致性 | 支持单线程操作,强一致性 |
MySQL体系结构
MySQL的体系结构分为四层,如下所示:
- 连接层:最上层是一些客户端的连接服务,主要完成一些类似于连接处理、授权认证、及相关的安全方案。服务器也会为安全接入的每个客户端验证它所具有的操作权限。
- 服务层:第二层架构主要完成大多数的核心服务功能,如 SQL 接口,并完成缓存的查询,SQL 的分析和优化,部分内置函数的执行。所有跨存储引擎的功能也在这一层实现,如过程、函数等。
- 引擎层:是存储数据、建立索引、更新/查询数据等技术的实现方式,真正的负责了 MySQL 中数据的存储和提取,服务器通过 API 和存储引擎进行通信。不同的存储引擎具有不同的功能,这样我们可以根据自己的需要,来选取合适的存储引擎。
- 存储层:主要是将数据存储在文件系统之上,并完成与存储引擎的交互。
InnoDB、MyISAM、Memory三种存储引擎对比
InnoDB 是一种兼顾高可靠性和高性能的通用存储引擎,在 MySQL 5.5 之后,InnoDB 是默认的 MySQL 引擎。特点如下:
- DML 操作遵循 ACID 模型,支持事务;
- 行级锁,提高并发访问性能;
- 支持外键约束,保证数据的完整性和正确性;
文件:
- xxx.ibd:xxx代表表名,InnoDB 引擎的每张表都会对应这样一个表空间文件,存储该表的表结构(frm、sdi)、数据和索引;
- 参数:
innodb_file_per_table
,决定多张表共享一个表空间还是每张表对应一个表空间,若innodb_file_per_table
为ON,则表示每张表对应一个表空间。
MyISAM 是 MySQL 早期的默认存储引擎。特点如下:
- 不支持事务,不支持外键;
- 支持表锁,不支持行锁;
- 访问速度快;
文件:
- xxx.sdi:存储表结构信息;
- xxx.MYD:存储数据;
- xxx.MYI:存储索引;
Memory 引擎的表数据是存储在内存中的,受硬件问题、断电问题的影响,只能将这些表作为临时表或缓存使用。特点如下:
- 存放在内存中,速度快;
- hash索引(默认);
文件:
- xxx.sdi: 存储表结构信息;
特点 | InnoDB | MyISAM | Memory |
---|---|---|---|
存储限制 | 64TB | 有 | 有 |
事务安全 | 支持 | - | - |
锁机制 | 行锁 | 表锁 | 表锁 |
B+tree索引 | 支持 | 支持 | 支持 |
Hash索引 | - | - | 支持 |
全文索引 | 支持(5.6版本之后) | 支持 | - |
空间使用 | 高 | 低 | N/A |
内存使用 | 高 | 低 | 中等 |
批量插入速度 | 低 | 高 | 高 |
支持外键 | 支持 | - | - |
不同存储引擎的选择
在选择存储引擎时,应该根据应用系统的特点选择合适的存储引擎。对于复杂的应用系统,还可以根据实际情况选择多种存储引擎进行组合。
- InnoDB:如果应用对事物的完整性有比较高的要求,在并发条件下要求数据的一致性,数据操作除了插入和查询之外,还包含很多的更新、删除操作,则 InnoDB 是比较合适的选择。
- MyISAM:如果应用是以读操作和插入操作为主,只有很少的更新和删除操作,并且对事务的完整性、并发性要求不高,那这个存储引擎是非常合适的。
- Memory:将所有数据保存在内存中,访问速度快,通常用于临时表及缓存。Memory 的缺陷是对表的大小有限制,太大的表无法缓存在内存中,而且无法保障数据的安全性。
绝大多数使用的为InnoDB。电商中的足迹和评论适合使用 MyISAM 引擎,缓存适合使用 Memory 引擎。
目前使用:MySQL一般用InnoDB引擎,MyISAM应用场景被mongodb替代,MyISAM应用场景被redis替代
数据库有哪些SQL语句分类
- DDL(Data Definition Language):数据定义语言,用来定义数据库对象(操作数据库、表结构、字段);
- DML(Data ManipulationLanguage):数据操作语言,用来对数据库表中的数据进行增加、删除、修改;
- DQL(Data Query Language):数据查询语言,用来查询数据库中表的记录;
- DCL(Data Control Language):数据控制语言,用来创建数据库用户、控制数据库的控制权限;
DQL 执行顺序
- 程序编写顺序:
SELECT -> FROM -> WHERE -> GROUP BY -> HAVING -> ORDER BY -> LIMIT
- 程序执行顺序:
FROM -> WHERE -> GROUP BY -> HAVING -> SELECT -> ORDER BY -> LIMIT
where 和 having 的区别
语法:SELECT 字段列表 FROM 表名 [ WHERE 条件 ] GROUP BY 分组字段名 [ HAVING 分组后的过滤条件 ];
- 执行时机不同:where是分组之前进行过滤,不满足where条件不参与分组;having是分组后对结果进行过滤。
- 判断条件不同:where不能对聚合函数进行判断,而having可以。
replace into 和 insert into 的区别
replace into
跟 insert into
功能类似,不同点在于:replace into
首先尝试插入数据到表中,如果发现表中已经有此行数据(根据主键或者唯一索引判断)则先删除此行数据,然后插入新的数据;否则,直接插入新数据。
truncate 和 drop 的区别
- TRUNCATE:删除表中的所有行,但保留表结构。可以快速清空表数据,通常比使用 DELETE 更高效。
- DROP:删除整个表,包括表结构和数据。表一旦被删除,无法恢复。
各种函数介绍(字符串、数值、日期、流程)
常用字符串函数如下:
函数 | 功能 |
---|---|
CONCAT(s1, s2, …, sn) | 字符串拼接,将s1, s2, …, sn拼接成一个字符串 |
LOWER(str) | 将字符串全部转为小写 |
UPPER(str) | 将字符串全部转为大写 |
LPAD(str, n, pad) | 左填充,用字符串pad对str的左边进行填充,达到n个字符串长度 |
RPAD(str, n, pad) | 右填充,用字符串pad对str的右边进行填充,达到n个字符串长度 |
TRIM(str) | 去掉字符串头部和尾部的空格 |
SUBSTRING(str, start, len) | 返回从字符串str从start位置起的len个长度的字符串 |
REPLACE(column, source, replace) | 替换字符串 |
substring_index | substring_index(“原字符串”,“截取字符”,截取位置N) 看下面实例 |
常见数值函数如下:
函数 | 功能 |
---|---|
CEIL(x) | 向上取整 |
FLOOR(x) | 向下取整 |
MOD(x, y) | 返回x/y的模(取余%) |
RAND() | 返回0~1内的随机数 |
ROUND(x, y) | 求参数x的四舍五入值,保留y位小数 |
常见日期函数如下:
函数 | 功能 |
---|---|
DATE(date) | 提取日期部分(年、月、日)而忽略时间部分 |
CURDATE() | 返回当前日期(年月日) |
CURTIME() | 返回当前时间 |
NOW() | 返回当前日期和时间 |
YEAR(date) | 获取指定date的年份 |
MONTH(date) | 获取指定date的月份 |
DAY(date) | 获取指定date的日期 |
DATE_ADD(date, INTERVAL expr type) | 返回一个加上时间间隔expr后的日期/时间值 |
DATEDIFF(date1, date2) | 返回date1和date2之间的天数(date1 - date2) |
date_format(date, ‘%Y-%m-%d %H:%i:%s’) | 提取date中指定格式的日期 |
timestampdiff(type, start_time, end_time) | 算时间差值,type可以为second、minute、hour等 |
常见流程函数如下:
函数 | 功能 |
---|---|
IF(value, t, f) | 如果value为true,则返回t,否则返回f |
IFNULL(value1, value2) | 如果value1不为空(null),返回value1,否则返回value2 |
CASE WHEN [ val1 ] THEN [ res1 ] … ELSE [ default ] END | 如果val1为true,返回res1,… 否则返回default默认值 |
CASE [ expr ] WHEN [ val1 ] THEN [ res1 ] … ELSE [ default ] END | 如果expr的值等于val1,返回res1,… 否则返回default默认值 |
介绍 MySQL 中的字段约束
-
概念:约束是作用于表中字段上的规则,用于限制存储在表中的数据。
-
目的:保证数据库中数据的正确、有效性和完整性。
-
分类:
约束 | 描述 | 关键字 |
---|---|---|
非空约束 | 限制该字段的数据不能为null | NOT NULL |
唯一约束 | 保证该字段的所有数据都是唯一、不重复的 | UNIQUE |
主键约束 | 主键是一行数据的唯一标识,要求非空且唯一 | PRIMARY KEY |
默认约束 | 保存数据时,如果未指定该字段的值,则采用默认值 | DEFAULT |
检查约束 | 保证字段值满足某一个条件 | CHECK( ) |
外键约束 | 用来让两张图的数据之间建立连接,保证数据的一致性和完整性 | FOREIGN KEY |
约束是作用于表中字段上的,可以在创建表/修改表的时候添加约束。
其中外键约束的删除/更新行为有如下几种:
行为 | 说明 |
---|---|
NO ACTION | 当在父表中删除/更新对应记录时,首先检查该记录是否有对应外键,如果有则不允许删除/更新(与RESTRICT一致) |
RESTRICT | 当在父表中删除/更新对应记录时,首先检查该记录是否有对应外键,如果有则不允许删除/更新(与NO ACTION一致) |
CASCADE | 当在父表中删除/更新对应记录时,首先检查该记录是否有对应外键,如果有则也删除/更新外键在子表中的记录 |
SET NULL | 当在父表中删除/更新对应记录时,首先检查该记录是否有对应外键,如果有则设置子表中该外键值为null(要求该外键允许为null) |
SET DEFAULT | 父表有变更时,子表将外键设为一个默认值(Innodb不支持) |
使用语法:在修改表时添加外键约束后面加 ON UPDATE 行为 ON DELETE 行为;
ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段) REFERENCES 主表名(主表字段名) ON UPDATE 行为 ON DELETE 行为;
内连接查询和外连接查询的区别
内连接:查询的是两张表交集的部分,即 A ∩ B
:
- 隐式内连接:
SELECT 字段列表 FROM 表1, 表2 WHERE 条件 ...;
- 显式内连接:
SELECT 字段列表 FROM 表1 [ INNER ] JOIN 表2 ON 连接条件 ...;
- 注意事项:显式性能比隐式高
左外连接:查询左表A的所有数据,以及两张表交集部分的数据。
- 语法:
SELECT 字段列表 FROM 表1 LEFT [ OUTER ] JOIN 表2 ON 条件 ...;
- 注意事项:A中所有表项必须都得有,交集中有对应B的表项也要显示出来。
右外连接:查询右表所有数据,以及两张表交集部分数据。
- 语法:
SELECT 字段列表 FROM 表1 RIGHT [ OUTER ] JOIN 表2 ON 条件 ...;
有哪些性能分析的语句
(1)查看执行频次
查看当前数据库的 INSERT, UPDATE, DELETE, SELECT 访问频次:SHOW [SESSION | GLOBAL] STATUS LIKE 'Com_______';
注意,session 是会话级别,表示只针对当前会话有效;global 表示对所有会话有效。
(2)慢查询日志
慢查询日志记录了所有执行时间超过指定参数(long_query_time,单位:秒,默认10秒)的所有SQL语句的日志。
MySQL 的慢查询日志默认没有开启,需要在MySQL的配置文件(/etc/my.cnf)中配置如下信息:
# 开启慢查询日志开关
slow_query_log=1
# 设置慢查询日志的时间为2秒,SQL语句执行时间超过2秒,就会视为慢查询,记录慢查询日志
long_query_time=2
日志文件位置:/var/lib/mysql/localhost-slow.log,日志中会记录慢查询的记录
(3)profile 语句
show profile
能在做 SQL 优化时帮我们了解时间都耗费在哪里。
- 通过
have_profiling
参数,能看到当前 MySQL 是否支持 profile 操作:SELECT @@have_profiling;
- profiling 默认关闭,查看 profile 是否开启:
SELECT @@profiling;
#0为关闭,1为开启 - 可以通过 set 语句在 session/global 级别开启 profiling:
SET profiling = 1;
- 查看所有语句的耗时:
show profiles;
(4)explain 语句
EXPLAIN 或者 DESC 命令获取 MySQL 如何执行 SELECT 语句的信息,包括在 SELECT 语句执行过程中表如何连接和连接的顺序。语法:直接在 select 语句之前加上关键字 explain / desc 即可。
解释 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。
- 当不查询表时,性能为 NULL,如
select 'A';
- 当访问系统表时,通常性能为 system;
- 根据主键和唯一索引进行查询时,通常性能为 const;
- 使用非唯一索引进行查询时,性能为 ref;
- index 是虽然用了索引,但在扫描索引时,遍历了整个索引树;
- all 为全表扫描;
- 当不查询表时,性能为 NULL,如
- possible_key:可能应用在这张表上的索引(可能有多个)。
- Key:实际上使用的索引,如果为 NULL,则表示没有使用索引。
- Key_len:表示索引中使用的字节数,该值为索引字段最大可能长度,并非实际使用长度,在不损失精确性的前提下,长度越短越好。
- rows:MySQL 认为必须要执行的行数,在 InnoDB 引擎的表中,是一个估计值,可能并不总是准确的。
- filtered:表示返回结果的行数占需读取行数的百分比,filtered的值越大越好。
- extra:额外信息。
数据库的优化方法
- 索引优化:区分度高列建索引、尽量使用联合索引、最频繁列放到最左侧、长字符串考虑前缀索引、尽量走聚集索引、避免回表查询。
- 表结构设计优化:消除冗余数据字段、字段太多时考虑多表用外键。
- sql语句优化:主键按顺序插入避免页分裂、尽量批量插入、order by / group by都可以考虑建索引、尽量使用 JOIN 代替子查询、性能排序count(字段) < count(主键) < count(1) ≈ count(*)。
- 分库分表:单机数据量大时考虑建立集群。
介绍MySQL中的视图
视图(View)是一种虚拟存在的表。视图中的数据并不在数据库中实际存在,行和列数据来自定义视图的查询中使用的表,并且是在使用视图时动态生成的。通俗的讲,视图只保存了查询的 SQL 逻辑,不保存查询结果。所以我们在创建视图的时候,主要的工作就落在创建这条 SQL 查询语句上。
使用视图的作用:
- 简单:视图不仅可以简化用户对数据的理解,也可以简化他们的操作。那些被经常使用的查询可以被定义为视图,从而使得用户不必为以后的操作每次指定全部的条件;
- 安全:数据库可以授权,但不能授权到数据库特定行和特定的列上。通过视图用户只能查询和修改他们所能见到的数据;
- 数据独立:视图可帮助用户屏蔽真实表结构变化带来的影响。
总而言之,类似于给表加上了一个外壳,通过这个外壳访问表的时候,只能按照所设计的方式进行访问与更新。
InnoDB 的行格式介绍
行格式(row_format),就是一条记录的存储结构。MySQL 5.0 之后引入了 Compact 行记录存储方式,Compact 是一种紧凑的行格式,设计的初衷就是为了让一个数据页中可以存放更多的行记录,从 MySQL 5.1 版本之后,行格式默认设置成 Compact。
Compact 行格式如下:
其实一共分为三个部分:记录的额外信息、三个隐藏字段、真实数据。下面依次来看看:
(1)记录的额外信息
记录的额外信息包含 3 个部分:变长字段长度列表、NULL 值列表、记录头信息。
- 变长字段长度列表:它只出现在数据表有变长字段的时候,如 varchar(n),会记录表中数据的真实长度。当数据表没有变长字段的时候,比如全部都是 int 类型的字段,这时候表里的行格式就不会有变长字段长度列表了。
- NULL 值列表:表中的某些列可能会存储 NULL 值,如果把这些 NULL 值都放到记录的真实数据中会比较浪费空间,所以 Compact 行格式把这些值为 NULL 的列存储到 NULL值列表中。如果存在允许 NULL 值的列,则每个列对应一个二进制位(bit):
- 二进制位的值为1时,代表该列的值为NULL。
- 二进制位的值为0时,代表该列的值不为NULL。
- 记录头信息:记录头信息是额外记录该列的属性、状态信息等。比如 delete_mask 字段:标识此条数据是否被删除,执行 detele 删除记录的时候,并不会真正的删除记录,只是将这个记录的 delete_mask 标记为 1。
(2)三个隐藏字段
- ROW_ID:隐藏主键,如果表结构没有指定主键,将会生成该隐藏字段。
- TRX_ID:最近修改事务ID,记录插入这条记录或最后一次修改该记录的事务ID。
- ROLL_PTR:回滚指针,指向这条记录的上一个版本,用于配合undo log,指向上一个版本。
(3)真实数据
就是每一列对应的真实数据。
varchar类型如何记录数据的真实长度
在MySQL中,VARCHAR(n) 数据类型用于存储可变长度的字符串,n 表示字符串的最大长度(字符数)。MySQL会在存储时记录实际使用的长度,这样可以有效利用空间。
具体来说,VARCHAR类型会使用1或2个字节来存储字符串的长度信息:
- 如果长度小于等于255字符,使用1个字节。
- 如果长度超过255字符,使用2个字节。
varchar(n) 中 n 最大取值为多少
一行记录最大能存储 65535 字节的数据,但是这个是包含「变长字段字节数列表所占用的字节数」和「NULL值列表所占用的字节数」。所以, 我们在算 varchar(n) 中 n 最大值时,需要减去这两个列表所占用的字节数。
- 如果一张表只有一个 varchar(n) 字段,且允许为 NULL,字符集为 ascii。varchar(n) 中 n 最大取值为 65532。计算公式:65535 - 变长字段字节数列表所占用的字节数 - NULL值列表所占用的字节数 = 65535 - 2 - 1 = 65532。
- 如果有多个字段的话,要保证所有字段的长度 + 变长字段字节数列表所占用的字节数 + NULL值列表所占用的字节数 <= 65535。
NULL会记录在表中吗?
在MySQL中,当一列的值为 NULL 时,MySQL不会在该列中存储实际的 NULL 值,而是使用一个特殊的位图来标识该行的 NULL 值。这个位图只需一个额外的字节,表示哪些列是 NULL,从而减少空间占用。
NULL位图
是在存储行数据时自动生成的,用于指示哪些列的值为 NULL。以下是关于 NULL 位图的详细说明:
- 位图的生成:在每一行的开头,MySQL会为该行的NULL位图分配一定的字节。这个位图的大小与行中允许NULL值的列数有关。每一位代表一个列,如果该位为1,则表示对应的列为NULL;如果为0,则表示该列有值。
- 位图的存储:NULL位图存储在行数据的开头部分,通常在行数据和列值之间。位图的大小取决于该行中NULL列的数量,每8个列使用1个字节来存储位图。
- 查询和操作:在查询时,MySQL会使用这个位图来快速判断某行的哪些列是NULL,从而优化查询性能。对于任何涉及NULL的操作,MySQL首先检查位图,然后决定是否执行相关操作。
行溢出后,MySQL 是怎么处理的
如果一个数据页存不了一条记录,InnoDB 存储引擎会自动将溢出的数据存放到「溢出页」中。
Compact 行格式针对行溢出的处理是这样的:当发生行溢出时,在记录的真实数据处只会保存该列的一部分数据,而把剩余的数据放在「溢出页」中,然后真实数据处用 20 字节存储指向溢出页的地址,从而可以找到剩余数据所在的页。
Compressed 和 Dynamic 这两种格式采用完全的行溢出方式,记录的真实数据处不会存储该列的一部分数据,只存储 20 个字节的指针来指向溢出页。而实际的数据都存储在溢出页中。
索引篇
什么是索引?为什么要用索引?
索引是帮助 MySQL 高效获取数据的数据结构(有序)。在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查询算法,这种数据结构就是索引。
总而言之,用索引就是为了查得快。如下举例:如果没有索引,查询某一条记录,则需要顺序遍历一遍表去找,速度很慢;如果有索引,建立数据结构来帮助查询,数据结构会指向数据,从而加快查询速度。
注意:是通过对索引列字段创建数据结构,然后找到后引用指向原列。
使用索引的优缺点
优点:
- 提高数据检索效率,降低数据库的IO成本;
- 通过索引列对数据进行排序,降低数据排序的成本,降低CPU的消耗;
缺点:
- 索引列也是要占用空间的;
- 索引大大提高了查询效率,但降低了更新的速度,比如 INSERT、UPDATE、DELETE;
索引的分类
索引的分类标准有很多,下面从多个角度来看索引的分类:
(1)根据索引的使用分类
分类 | 含义 | 特点 | 关键字 |
---|---|---|---|
主键索引 | 针对于表中主键创建的索引 | 默认自动创建,只能有一个 | PRIMARY |
唯一索引 | 避免同一个表中某数据列中的值重复 | 可以有多个 | UNIQUE |
常规索引 | 快速定位特定数据 | 可以有多个 | |
前缀索引 | 对字段的前几个字符建立的索引,而不是在整个字段上建立索引 | 可以有多个 |
对某个字段创建主键时,会自动生成主键索引。
对某个字段创建唯一约束时,会自动生成唯一索引。
(2)根据索引建立对应的字段分类
分类 | 含义 |
---|---|
单列索引 | 一个索引只包含单个列 |
联合索引 | 一个索引包含了多个列 |
(3)根据索引的存储形式分类
分类 | 含义 | 特点 |
---|---|---|
聚集索引(Clustered Index) | 将数据存储与索引放一块,索引结构的叶子节点保存了行数据 | 必须有,而且只有一个 |
二级索引(Secondary Index) | 将数据与索引分开存储,索引结构的叶子节点关联的是对应的主键 | 可以存在多个 |
(4)根据索引的数据结构分类
索引结构 | 含义 |
---|---|
B+Tree | 最常见的索引类型,大部分引擎都支持B+树索引 |
Hash | 底层数据结构是用哈希表实现,只有精确匹配索引列的查询才有效,不支持范围查询 |
R-Tree(空间索引) | 空间索引是 MyISAM 引擎的一个特殊索引类型,主要用于地理空间数据类型,通常使用较少 |
Full-Text(全文索引) | 是一种通过建立倒排索引,快速匹配文档的方式,类似于 Lucene, Solr, ES |
索引的底层数据结构
索引底层的数据结构有 B+Tree
、哈希表
等,先来分析一下 B+Tree。
首先思考一下,为什么索引不用普通二叉树来实现?
如果采用二叉树来做索引数据结构时,有如下缺点∶
- 顺序插入时,会形成一个链表,查询性能大大降低。
- 大数据量情况下,层级较深,检索速度慢。
其中顺序插入的问题可由红黑树解决,但是红黑树也存在大数据量情况下,层级较深,检索速度慢的问题。
为了解决上述问题,可以使用 B-Tree 结构。
B-树是一颗中序遍历结果有序的多路平衡树。不同于二叉树,B-树中的结点可以有多个孩子结点,二叉树只能有两个孩子结点。B-树的高度为 log
标签:事务,记录,数据库,查询,索引,MySQL,日志,数据 From: https://blog.csdn.net/weixin_46571171/article/details/142713532