
🐇明明跟你说过:个人主页
🏅个人专栏:《MySQL技术精粹》🏅
🔖行路有良友,便是天堂🔖
目录
[1.1 什么是数据表](#1.1 什么是数据表)
[1.2 如何设计数据表](#1.2 如何设计数据表)
[2.1 什么是索引](#2.1 什么是索引)
[2.2 为什么需要索引](#2.2 为什么需要索引)
[2.3 索引的基本类型](#2.3 索引的基本类型)
[3.4 如何选择合适的索引](#3.4 如何选择合适的索引)
[3.1 数值类型](#3.1 数值类型)
[3.2 字符串类型](#3.2 字符串类型)
[3.3 日期和时间类型](#3.3 日期和时间类型)
[4.1 存储引擎 (Storage Engines)](#4.1 存储引擎 (Storage Engines))
[4.2 表的存储格式](#4.2 表的存储格式)
[4.3 MySQL 数据存储的物理结构](#4.3 MySQL 数据存储的物理结构)
一、引言
1、什么是MySQL
MySQL 是一个开源的关系型数据库管理系统(RDBMS),基于 SQL(结构化查询语言)来管理数据库中的数据。它是最流行的数据库管理系统之一,广泛应用于各类 Web 应用程序和软件系统中,尤其是在 LAMP(Linux、Apache、MySQL、PHP/Perl/Python)堆栈中扮演着核心角色。

2、MySQL适用场景
1. Web应用开发
MySQL 最常用于 Web 应用程序的后台数据库,尤其是在 LAMP(Linux、Apache、MySQL、PHP/Python/Perl)或 MERN(MongoDB、Express.js、React、Node.js)架构中,MySQL 作为数据库解决方案广泛应用于:
- **内容管理系统(CMS):**如 WordPress、Drupal、Joomla 等,通常使用 MySQL 存储文章、用户、评论等数据。
- **电子商务平台:**如 Magento、PrestaShop 和 OpenCart 等,MySQL 用于存储产品目录、订单数据、用户信息等。
- **社交媒体应用:**MySQL 可以存储用户数据、朋友关系、帖子、评论等信息。
- **在线论坛与博客:**如 Discourse、phpBB 等,MySQL 可以管理帖子、用户账户、评论等内容。
2. 内容管理与发布系统
MySQL 广泛用于内容管理系统(CMS),如 WordPress、Drupal 和 Joomla。它存储网站的内容(文章、图片、视频、评论、用户信息等)以及管理用户权限和访问控制的元数据。MySQL 在这些系统中的高效查询和可扩展性使其成为理想选择。
3. 电子商务系统
电子商务平台(如 Magento、WooCommerce、PrestaShop)依赖于 MySQL 来存储产品、订单、客户、支付、库存等信息。MySQL 支持高并发的查询和交易,确保订单处理的快速响应。它的事务处理特性确保了订单数据的一致性和完整性。

二、MySQL的数据存储与检索
1、数据表设计
1.1 什么是数据表
在 MySQL 中,数据表是用来存储数据的结构。可以将数据表想象成一个 Excel 表格,每一行代表一条记录,每一列代表一个数据字段(属性)。比如,一个存储用户信息的表,可能有字段:用户ID 、用户名 、电子邮箱 、创建时间等。
1.2 如何设计数据表
设计数据表时,我们需要考虑以下几个重要方面:
字段(列)的选择
每个数据表都会有多个字段。字段是表中数据的属性,决定了你能存储什么样的数据。举个例子:
假设你要设计一个存储"用户信息"的数据表,可能会有以下字段:
- **user_id:**用户的唯一标识符(整数型)。
- **username:**用户名(字符串类型)。
- **email:**电子邮件地址(字符串类型)。
- **created_at:**账号创建时间(日期时间类型)。
每个字段都有对应的数据类型,比如 INT 表示整数,VARCHAR 表示可变长度的字符串,DATETIME 表示日期时间等。选择正确的数据类型可以节省存储空间,提升查询效率。
主键(Primary Key)
主键是数据表中唯一标识一行数据的字段,它的值不能重复,不能为空。每个数据表应该有一个主键。通常我们用"自增ID"作为主键,它会自动为每一条记录分配一个唯一的 ID。
比如,user_id 字段可以作为users表的主键。它保证了每个用户在表中都有一个唯一标识。

外键(Foreign Key)
外键是用来在两个数据表之间建立关联的字段。它是一个数据表中的字段,指向另一个数据表的主键。外键可以帮助保持数据一致性,确保关联的记录始终有效。
举个例子,如果有一个"订单"表和"用户"表,订单表中可能包含一个 user_id 字段,用来表示订单属于哪个用户。这个 user_id 字段就是外键,它指向"用户"表中的主键user_id。
数据规范化(Normalization)
数据规范化是指通过合理地划分数据表来减少冗余数据,并确保数据一致性。常见的规范化范式有:
- **第一范式(1NF):**保证每列的数据都是原子性的,即每个字段只能包含一个值。
- **第二范式(2NF):**在满足 1NF 的基础上,保证每个非主键字段完全依赖于主键字段。
- **第三范式(3NF):**在满足 2NF 的基础上,确保没有非主键字段依赖于其他非主键字段。
例如,假设你有一个包含用户信息的表,字段包括 **user_id、username、email、city(用户城市)**等。如果你将所有用户信息存储在一个表中,就可能出现冗余。例如,许多用户都在同一个城市,这样会导致城市名重复出现。为了减少冗余,可以将"城市"单独放到另一个表中,建立一个与用户表的关联。

2、索引设计
2.1 什么是索引
可以把索引理解为一本书的"目录"。当你想要找到书中的某一章或某一节内容时,你不需要从头到尾阅读每一页,而是可以直接查阅目录,快速定位到需要的地方。
在 MySQL 中,索引就是为了加速查询操作,帮助数据库更快速地找到需要的数据。没有索引,数据库就需要逐行扫描(全表扫描)来查找数据,这会非常慢。
2.2 为什么需要索引
数据库在存储大量数据时,查询效率可能会非常低。比如,有一个包含数百万行数据的表,如果每次查询都要扫描整个表,那就会非常浪费时间和资源。
通过为数据表创建索引,MySQL 可以通过查找索引来直接定位到相关记录,而不必扫描整个表。这样可以显著提升查询性能。

2.3 索引的基本类型
MySQL 支持几种常见的索引类型,每种类型有不同的使用场景。
单列索引
单列索引是最常见的一种索引类型,它为表中的一个字段创建索引。比如,如果你经常按 email 字段查询用户信息,可以为 email字段创建单列索引。
CREATE INDEX idx_email ON users(email);
这种索引只会加速基于单个字段的查询。
复合索引(多列索引)
复合索引是由多个字段组成的索引。当你经常用多个字段一起进行查询时,可以为这些字段创建复合索引。比如,如果你经常根据 username 和email两个字段同时查询用户信息,可以创建复合索引。
CREATE INDEX idx_username_email ON users(username, email);
复合索引的顺序非常重要。它会根据索引字段的顺序来优化查询。如果你经常查询 username 和 email, 那么这个复合索引会非常有效。但如果查询条件只包含 email ,而没有 username,这个索引的效果就不好。
唯一索引
唯一索引保证了列中每个值的唯一性。一般来说,主键就是唯一索引。如果你想确保某个字段的值不能重复,可以使用唯一索引。
CREATE UNIQUE INDEX idx_unique_email ON users(email);
这样,email 字段就无法插入重复的值。
全文索引
全文索引(FULLTEXT)用于加速对文本数据的搜索,尤其是对于大文本字段(如文章、评论等)。它允许对文本中的单词进行快速搜索。全文索引适用于搜索操作,而不是精确匹配。
CREATE FULLTEXT INDEX idx_fulltext_content ON articles(content);
3.4 如何选择合适的索引
索引并不是越多越好,过多的索引会导致数据库在执行插入、删除和更新操作时变得更慢。所以,在设计索引时,需要根据查询的实际需求来选择合适的索引。
查询频繁的字段
- 为那些在查询中经常作为条件的字段创建索引。例如,如果你经常根据 email 来查找用户,就可以为 email 创建索引。
复合索引
- 如果查询经常使用多个字段的组合(比如 username 和 email),可以考虑创建复合索引,而不是为每个字段单独创建索引。
避免冗余索引
- 如果已经有复合索引包含了某个字段,就不需要为该字段单独创建索引了。否则,索引会变得冗余,影响性能。

3、数据类型
3.1 数值类型
数值类型用于存储整数和浮动小数点的数字。MySQL 提供了多种数值类型,主要分为整数类型、浮动小数点类型和定点数类型。
整数类型
整数类型用于存储没有小数部分的数字。常见的整数类型包括:
- TINYINT: 范围为 -128 到 127 (有符号)或 0 到 255(无符号)。用于存储非常小的整数。
- SMALLINT: 范围为 -32,768 到 32,767 (有符号)或 0 到 65,535(无符号)。
- MEDIUMINT: 范围为 -8,388,608 到 8,388,607 (有符号)或 0 到 16,777,215(无符号)。
- INT(或 INTEGER): 范围为**-2,147,483,648** 到 2,147,483,647 (有符号)或 0 到 4,294,967,295(无符号)。这是最常用的整数类型。
- BIGINT: 范围为 -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807 (有符号)或0 到 18,446,744,073,709,551,615(无符号)。用于存储非常大的整数。
浮动小数点类型
浮动小数点类型用于存储带有小数部分的数值。常见的浮动小数点类型有:
- **FLOAT:**单精度浮点数。存储的数值精度较低,适合存储占用空间较小的数值。其精度为 7 位十进制数。
- **DOUBLE:**双精度浮点数,精度更高,适合存储需要高精度的数值。其精度为 15 位十进制数。
- **REAL:**实际上是 DOUBLE 类型的别名。

3.2 字符串类型
字符串类型用于存储各种文本数据,MySQL 提供了多种类型的字符串字段。
字符类型
- CHAR(M): 固定长度的字符串,M表示字符的长度,最大可达 255 字符。即使插入的字符串长度小于 M,它也会用空格填充至指定的长度。
- VARCHAR(M): 可变长度的字符串,M 表示最大字符长度,最大值为 65,535 字符。VARCHAR 根据实际存储的字符长度来分配空间,不会浪费空间。
- **TEXT:**用于存储大文本数据,最大长度为 65,535 字符。TEXT 类型用于存储超过 VARCHAR 能存储的字符串,通常用于存储长文本内容。
- **TINYTEXT:**最大长度为 255 字符的文本。
- **MEDIUMTEXT:**最大长度为 16,777,215 字符的文本。
- **LONGTEXT:**最大长度为 4,294,967,295 字符的文本。
二进制数据类型
二进制数据类型用于存储原始二进制数据,如图像、文件等。
- **BINARY(M):**固定长度的二进制数据,M 表示长度,最大可达 255 字节。
- **VARBINARY(M):**可变长度的二进制数据,M 表示最大字节数,最大为 65,535 字节。
- BLOB: 用于存储大块二进制数据,最大为 65,535 字节。BLOB 与 TEXT 类似,但用于二进制数据。
- **TINYBLOB:**最大为 255 字节的二进制数据。
- **MEDIUMBLOB:**最大为 16,777,215 字节的二进制数据。
- **LONGBLOB:**最大为 4,294,967,295 字节的二进制数据。

3.3 日期和时间类型
日期和时间类型用于存储日期和时间信息,MySQL 提供了多种类型来表示不同的日期和时间。
- **DATE:**用于存储日期,格式为 YYYY-MM-DD,范围是 1000-01-01 到 9999-12-31。
- **DATETIME:**用于存储日期和时间,格式为 YYYY-MM-DD HH:MM:SS,范围是 1000-01-01 00:00:00 到 9999-12-31 23:59:59。
- **TIMESTAMP:**用于存储时间戳,表示从 1970-01-01 00:00:00 UTC 到当前时间的秒数。通常用于记录数据的创建或修改时间。范围是 1970-01-01 00:00:01 到 2038-01-19 03:14:07。
- **TIME:**用于存储时间,格式为 HH:MM:SS,范围是 -838:59:59 到 838:59:59。
- **YEAR:**用于存储年份,格式为 YYYY,范围是 1901 到 2155。
4、存储格式
4.1 存储引擎 (Storage Engines)
MySQL 支持多种存储引擎,每种引擎有不同的数据存储格式和特性。常见的存储引擎有:
InnoDB(默认存储引擎)
- **事务支持:**InnoDB 是 MySQL 默认的存储引擎,支持事务、ACID(原子性、一致性、隔离性、持久性)特性。
- **行级锁定:**InnoDB 支持行级锁定,提高并发性能。
- **数据存储格式:**InnoDB 使用聚集索引(Clustered Index)来存储数据。数据表中的数据是按主键顺序存储的,因此主键的选择对性能有重要影响。
- **数据文件:**InnoDB 数据存储在 ibdata 文件中(默认情况下),此外还有每个表的独立表空间文件(.ibd 文件)用于存储表和索引数据。
- **表的存储格式:**每个 InnoDB 表都有自己的表空间文件。数据和索引存储在一个单独的文件中,这个文件包含了该表的所有信息。

MyISAM
- **不支持事务:**MyISAM 不支持事务,不提供 ACID 保证,但由于其简单性和高效性,通常适用于读多写少的应用场景。
- **表级锁定:**MyISAM 使用表级锁定,适用于并发性较低的情况,多个查询可以共享锁,但对写操作会造成阻塞。
- **数据存储格式:**MyISAM 使用的是非聚集索引的存储格式。数据和索引分别存储在不同的文件中:数据存储在 .MYD 文件中,索引存储在 .MYI 文件中。
- **存储效率:**MyISAM 通常比 InnoDB 存储效率高,但不适用于对事务和并发要求较高的场景。
MEMORY
- **内存存储:**MEMORY 引擎将所有数据存储在内存中,因此它提供非常快速的读写操作。但因为数据存储在内存中,系统重启后数据将丢失。
- **数据存储格式:**数据表存储在内存中,类似于临时表。数据文件实际上存在于 RAM 中,不会被写入磁盘。
- **适用场景:**适用于存储临时数据或需要高速读写的操作,比如缓存。
CSV
- **以逗号分隔的文件:**CSV 存储引擎将每个表的数据存储为一个以逗号分隔值的文本文件,每行代表一条记录。
- **适用场景:**适用于需要将数据导入或导出为 CSV 格式的应用场景。它不适用于高效查询,因为缺乏索引。

ARCHIVE
- **压缩存储:**ARCHIVE 引擎用于存储大量历史数据,可以压缩数据以节省空间。数据只能追加,不能进行更新或删除。
- **适用场景:**适合用于存储日志或归档数据,不适合频繁更新的表。
NDB(Clustered)
- **高可用性和分布式存储:**NDB 是 MySQL 集群的存储引擎,适用于分布式数据库架构,支持多节点的高可用性和高扩展性。
- **数据存储格式:**NDB 数据存储在集群的不同节点中,表和索引被分布在集群中。
4.2 表的存储格式
MySQL 中的数据表存储格式,取决于所使用的存储引擎。常见的存储格式有两种:聚集索引存储格式和非聚集索引存储格式。
聚集索引存储格式(InnoDB)
- 在 InnoDB 存储引擎中,数据表默认使用聚集索引(Clustered Index)存储。
- 聚集索引是将数据行按照主键值排序并存储在数据文件中。每个数据表的实际数据行就是主键索引的叶子节点。
- 如果没有主键,InnoDB 会选择一个唯一索引作为聚集索引;如果表没有唯一索引,InnoDB 会隐式创建一个 6 字节的主键作为聚集索引。
- 优势:通过聚集索引存储数据,查询效率高,尤其是基于主键或索引的查询。
- 劣势:对于大量更新或删除操作,聚集索引会导致数据的物理存储块的频繁调整,可能会影响性能。
非聚集索引存储格式(MyISAM)
- 在 MyISAM 存储引擎中,数据表使用非聚集索引(Non-clustered Index)存储。
- 数据表的记录和索引是独立存储的。索引存储在一个单独的文件(.MYI ),数据存储在另一个文件(.MYD)中。
- 在查询时,首先通过索引查找记录的地址,然后再根据地址去读取对应的记录。
- 优势:对只读查询性能较好,存储和删除操作简单,索引文件和数据文件分开。
- 劣势:查询时需要多次磁盘访问,效率相对较低。

4.3 MySQL 数据存储的物理结构
MySQL 在磁盘上存储数据时,使用不同的存储引擎和存储格式,每种存储引擎有不同的文件存储结构。
InnoDB 存储格式
- 表空间:InnoDB 使用表空间来存储数据和索引。表空间有两种类型:
- 共享表空间: 所有的 InnoDB 表都存储在同一个表空间文件中(通常是ibdata1)。这使得多个表的数据存储在一个文件中,增加了管理的复杂性,但也提供了更高的空间利用率。
- 独立表空间: 每个表都使用一个独立的文件存储(.ibd文件),适用于需要管理单独表的情况。
- **数据页:**InnoDB 使用固定大小的数据页(通常是 16KB)来存储表的数据和索引。每个页由多个行组成,每个页通过 B+ 树索引链接。
MyISAM 存储格式
- **数据文件(.MYD 文件):**存储表的实际数据。
- **索引文件(.MYI 文件):**存储表的索引信息。
- **存储结构:**MyISAM 使用一个非聚集索引结构,每个数据表的记录和索引是分开存储的。每个 MyISAM 表的索引和数据都是独立的文件。
MEMORY 存储格式
- **内存存储:**MEMORY 引擎将所有的数据存储在内存中。数据表在内存中存储,表的数据会保存在操作系统的内存中,而不是写入磁盘。
- **临时数据:**当 MySQL 重启时,内存中的数据将丢失,适合用于存储临时的数据。

💕💕💕每一次的分享都是一次成长的旅程,感谢您的陪伴和关注。希望这些关于MySQL的文章能陪伴您走过技术的一段旅程,共同见证成长和进步!😺😺😺
🧨🧨🧨让我们一起在技术的海洋中探索前行,共同书写美好的未来!!!