文章目录
- 一、前置知识
- 二、MySQL 存储引擎(先了解,初步有个印象)
- 2.1 MySQL 存储引擎的概念
- 2.2 查询 MySQL 中支持的存储引擎
- 2.3 InnoDB 存储引擎
- 2.4 MyISAM 存储引擎
- 2.5 MEMORY 存储引擎
- 2.6 如何选择 MySQL 存储引擎?
- 三、MySQL 数据类型
- 3.1 数字类型
- 3.2 日期和时间类型
- 3.2.1 补充说明:YEAR 类型
- 3.2.2 补充说明:TIME 类型
- 3.2.3 补充说明:Date 类型
- 3.2.4 补充说明:DATETIME 类型
- 3.2.5 补充说明:TIMESTAMP 类型
- 3.3 字符串类型
- 3.4 MySQL 数据类型的选择
使用存储引擎可以加快查询的速度,并且每一种引擎都具有不同的含义。数据类型是数据的一种属性,其可以决定数据的存储格式、有效范围和相应的限制,我们应该了解如何选择合适的数据类型。本文将对 MySQL 的存储引擎和数据类型的使用进行详细讲解。本文知识架构及重难点如下:
MySQL 存储引擎大部分会在面试的时候询问到,初学的时候了解即可,重点要掌握和熟悉 MySQL 数据类型相关的知识点。
一、前置知识
一、数据库开发与实战专栏导学及数据库基础概念入门
二、MySQL 介绍及 MySQL 安装与配置
三、MySQL 数据库的基本操作
二、MySQL 存储引擎(先了解,初步有个印象)
存储引擎其实就是如何存储数据、如何为存储的数据建立索引和如何更新、查询数据等技术的实现方法。因为在关系数据库中数据是以表的形式存储的,所以存储引擎也可以称为 表类型(即存储和操作此表的类型)。 在 Oracle 和 SQL Server 等数据库中只有一种存储引擎,所有数据存储管理机制都是一样的;而 MySQL 数据库提供了多种存储引擎,用户可以根据不同的需求为数据表选择不同的存储引擎,也可以根据需要编写自己的存储引擎。
2.1 MySQL 存储引擎的概念
MySQL 中的数据用各种不同的技术存储在 文件(或者内存) 中。每一种技术都使用不同的存储机制、索引技巧、锁定水平并且最终提供广泛的、不同的功能和能力。通过选择不同的技术,能够获得额外的速度或者功能,从而改善应用的整体功能。这些不同的技术以及配套的相关功能在 MySQL 中被称作 存储引擎(也称作表类型)。 MySQL 默认配置了许多不同的存储引擎,可以预先设置或者在 MySQL 服务器中启用。可以选择适用于服务器、数据库和表格的存储引擎,以便在选择如何存储信息、如何检索信息以及需要的数据结合什么性能和功能时为其提供最大的灵活性。MySQL 的核心就是存储引擎。
2.2 查询 MySQL 中支持的存储引擎
MySQL8.0 支持的存储引擎有 FEDERATED、MEMORY、InnoDB、PERFORMANCE_SCHEMA、MyISAM、MRG_MYISAM、BLACKHOLE、CSV、ARCHIVE 等。可以使用 SHOW ENGINES;
语句查看系统所支持的引擎类型,结果如下图所示:
查询结果中的 Engine 参数指的是存储引擎的名称,Support 参数指的是 MySQL 是否支持该类引擎,YES 表示支持,NO 表示不支持,DEFAULT 表示该引擎为当前默认的存储引擎;Comment 参数指对该引擎的评论。从查询结果中可以看出,MySQL 支持多个存储引擎,其中 InnoDB 为默认存储引擎。
有几种存储引擎的名字还有同义词,例如,MRG_MyISAM 和 NDBCLUSTER 分别是 MERGE 和 NDB 的同义词。存储引擎 MEMORY 和 InnoDB 在早期分别称为 HEAP 和 Innobase。虽然后面两个名字仍能被识别,但是已经被废弃了。
下面简要描写几种存储引擎,后面会对其中的几种 (主要是 InnoDB、MyISAM 和 MEMORY 存储引擎) 进行详细讲解:
存储引擎 | 描述 |
---|---|
ARCHIVE | 用于数据存档的引擎,数据被插入后就不能在修改了,且不支持索引。 |
CSV | 在存储数据时,会以逗号作为数据项之间的分隔符。 |
BLACKHOLE | 会丢弃写操作,该操作会返回空内容。 |
FEDERATED | 将数据存储在远程数据库中,用来访问远程表的存储引擎。 |
InnoDB | 具备外键支持功能的事务处理引擎 |
MEMORY | 置于内存的表 |
MERGE | 用来管理由多个 MyISAM 表构成的表集合 |
MyISAM | 主要的非事务处理存储引擎 |
NDB | MySQL 集群专用存储引擎 |
PERFORMANCE_SCHEMA | 该引擎主要用于收集数据库服务器性能参数 |
如果想要知道当前 MySQL 服务器采用的默认存储引擎,可以执行以下两条 SQL 语句:
SELECT @@default_storage_engine;
SHOW VARIABLES LIKE 'default_storage_engine%';
如下图所示:
从上图中可以看出,当前 MySQL 服务器采用的默认存储引擎是 InnoDB。有些表根本不用来存储长期数据,实际上用户需要完全在服务器的 RAM 或特殊的临时文件中创建和维护这些数据,以确保高性能,但这样也存在很高的不稳定风险。还有一些表只是为了简化对一组相同表的维护和访问,为同时与所有这些表交互提供一个单一接口。另外,还有一些其他特别用途的表,但重点是:MySQL 支持很多类型的表,每种类型都有自己特定的作用、优点和缺点。MySQL 还相应地提供了很多不同的存储引擎,可以以最适合于应用需求的方式存储数据。MySQL 有多个可用的存储引擎,下面主要介绍InnoDB、MyISAM 和 MEMORY 存储引擎。
2.3 InnoDB 存储引擎
InnoDB 已经开发了十余年,遵循 CNU 通用公开许可(GPL)发行。InnoDB 已经被一些重量级 Internet 公司所采用,如 Yahoo!、Slashdot 和 Google,为用户操作非常大的数据库提供了一个强大的解决方案。InnoDB 给 MySQL 的表提供了事务、回滚、崩溃修复能力和多版本并发控制的事务安全。自 MySQL3.23.34a 开始包含 InnoDB 存储引擎。InnoDB 是 MySQL 上第一个提供外键约束的表引擎,而且 InnoDB 对事务处理的能力也是 MySQL 其他存储引擎所无法比拟的。
InnoDB 存储引擎中支持自动增长列 AUTO_INCREMENT。自动增长列的值不能为空,且值必须唯一。MySQL 中规定自增列必须为主键。在插入值时,如果自动增长列不输入值,则插入的值为自动增长后的值;如果输入的值为 0或空(NULL),则插入的值也为自动增长后的值;如果插入某个确定的值,且该值在前面没有出现过,则可以直接插入。InnoDB 存储引擎中支持外键(FOREIGN KEY)。外键所在的表为子表,外键所依赖的表为父表。父表中被子表外键关联的字段必须为主键。当删除、更新父表的某条信息时,子表也必须有相应的改变。InnoDB 存储引擎中,创建的表的表结构存储在 .frm文件 中。数据和索引存储在 innodb_data_home_dir 和 innodb_data_file_path 表空间中。
InnoDB 存储引擎的优势在于提供了良好的事务管理、崩溃修复能力和并发控制,缺点是其读写效率稍差,占用的数据空间相对比较大。InnoDB 表是如下情况的理想引擎:
- 更新密集的表: InnoDB存储引擎特别适合处理多重并发的更新请求。
- 事务: InnoDB 存储引擎是唯一支持事务的标准 MySQL 存储引擎,这是管理敏感数据(如金融信息和用户注册信息)所必需的。
- 自动灾难恢复: 与其他存储引擎不同,InnoDB 表能够自动从灾难中恢复。虽然 MyISAM 表也能在灾难后修复,但其过程要长得多。
Oracle 的 InnoDB 存储引擎广泛应用于基于 MySQL 的 Web、电子商务、金融系统、健康护理以及零售应用。因为 InnoDB 可提供高效的 ACID 独立性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)兼容事务处理能力,以及独特的高性能和具有可扩展性的构架要素。另外,InnoDB 设计用于事务处理应用,这些应用需要处理崩溃恢复、参照完整性、高级别的用户并发数,以及响应时间超时服务水平。在 MySQL 5.5 中,最显著的增强性能是将 InnoDB 作为默认的存储引擎。在 MyISAM 以及其他表类型依然可用的情况下,用户无须更改配置,就可构建基于 InnoDB 的应用程序。
2.4 MyISAM 存储引擎
MyISAM 存储引擎是 MySQL 中常见的存储引擎,曾是 MySQL 的默认存储引擎。MyISAM 存储引擎是基于 ISAM 存储引擎发展起来的,它弥补了 ISAM 的很多不足,增加了很多有用的扩展。
1、MyISAM 存储引擎的文件类型。 MyISAM 存储引擎的表存储成3个文件。文件的名字与表名相同,扩展名包括 .frm、.MYD 和 .MYI。
.frm:存储表的结构。
.MYD:存储数据,是 MYData 的缩写。
.MYI:存储索引,是 MYIndex 的缩写。
2、MyISAM 存储引擎的存储格式。 基于 MyISAM 存储引擎的表支持3种不同的存储格式,包括静态、动态和压缩。
MyISAM 静态。 如果所有表列的大小都是静态的(即不使用 xBLOB、xTEXT或 VARCHAR 数据类型),MySQL 就会自动使用静态 MyISAM 格式。使用这种存储格式的表性能非常高,因为在维护和访问以预定义格式存储的数据时开销很低。但是,这项优点要以空间为代价,因为需要分配给每列最大空间,而无论该空间是否真正地使用。
MyISAM 动态。 如果有表列(即使只有一列)定义为动态的(使用xBLOB、xTEXT或VARCHAR),MySQL 就会自动使用动态格式。虽然 MyISAM 动态表占用的空间比静态格式所占空间少,但空间的节省带来了性能的下降。如果某个字段的内容发生改变,则其位置很可能就需要移动,这会导致碎片的产生。随着数据集中的碎片增加,数据访问性能就会相应降低。这个问题有以下两种修复方法。
尽可能使用静态数据类型
经常使用 OPTIMIZE TABLE 语句,它会整理表的碎片,恢复由于表更新和删除而导致的空间丢失。
MyISAM 压缩。 有时会创建在整个应用程序生命周期中都只读的表。如果是这种情况,就可以使用 myisampack 工具将其转换为 MyISAM 压缩表来节约空间。在给定硬件配置下(如快速的处理器和低速的硬盘驱动器),性能的提升将相当显著。
MyISAM 存储引擎的优缺点。MyISAM 存储引擎的优势在于占用空间小,处理速度快;缺点是不支持事务的完整性和并发性。
2.5 MEMORY 存储引擎
MEMORY 存储引擎是 MySQL 中的一类特殊的存储引擎,其使用存储在内存中的内容来创建表,而且所有数据也放在内存中,这与 InnoDB 和 MyISAM 存储引擎不同。下面将对 MEMORY 存储引擎的文件存储形式、索引类型、存储周期和优缺点等进行讲解。
1、MEMORY 存储引擎的文件存储形式。 每个基于 MEMORY 存储引擎的表实际对应一个磁盘文件。该文件的文件名与表名相同,类型为 frm。 该文件中只存储表的结构,而其数据文件都是存储在内存中。这样有利于对数据的快速处理,提高整个表的处理效率。值得注意的是,服务器需要有足够的内存来维持 MEMORY 存储引擎的表的使用。如果不再使用,可以释放这些内容,甚至可以删除不需要的表。
2、MEMORY 存储引擎的索引类型。 MEMORY 存储引擎默认使用 哈希(HASH) 索引,其速度要比使用 B树(BTREE) 索引快。如果读者希望使用B树索引,可以在创建索引时选择使用。
3、MEMORY 存储引擎的存储周期。 MEMORY 存储引擎通常很少用到,因为 MEMORY 表的所有数据是存储在内存上的,如果内存出现异常就会影响数据的完整性。如果重启机器或者关机,表中的所有数据将消失。因此,基于 MEMORY 存储引擎的表生命周期很短,一般都是一次性的。
4、MEMORY 存储引擎的优缺点。 MEMORY 表的大小是受到限制的。表的大小主要取决于两个参数,分别是 max_rows 和 max_heap_table_size。 其中,max_rows 可以在创建表时指定;max_heap_table_size 的大小默认为16MB,可以按需要进行扩大。MEMORY 表存在于内存中的特性,决定了这类表的处理速度非常快。但是,其数据易丢失,生命周期短。创建 MySQL MEMORY 存储引擎的出发点是速度。为得到最快的响应时间,采用的逻辑存储介质是系统内存。虽然在内存中存储表数据确实会提高性能,但是,当 mysqld 守护进程崩溃时,所有的 MEMORY 数据都会丢失。MEMORY 表不支持 VARCHAR、BLOB 和 TEXT 数据类型,因为这种表类型按固定长度的记录格式存储。此外,MySQL 4.1.0 之前的版本不支持自动增加列(通过 AUTO_INCREMENT 属性)。当然,要记住 MEMORY 表只用于特殊的范围,不会用于长期存储数据。基于其这个缺陷,选择 MEMORY 存储引擎时要特别小心。当数据有如下情况时,可以考虑使用 MEMORY 表。
- 暂时:目标数据只是临时需要,在其生命周期中必须立即可用。
- 相对无关:存储在 MEMORY 表中的数据如果突然丢失,不会对应用服务产生实质的负面影响,而且不会对数据完整性有长期影响。
如果使用 MySQL 4.1 及其之前版本,MEMORY 的搜索比 MyISAM 表的搜索效率要低,因为 MEMORY 表只支持散列索引,这需要使用整个键进行搜索。但是,MySQL 4.1 之后的版本同时支持散列索引和B树索引。B树索引优于散列索引的是,可以使用部分查询和通配查询,也可以使用 <、>和>=
等操作符方便数据挖掘。
2.6 如何选择 MySQL 存储引擎?
每种存储引擎都有各自的优势,不能笼统地说谁比谁更好,只有适合与不适合。下面根据其不同的特性,给出选择存储引擎的建议。
1、InnoDB 存储引擎: 用于事务处理应用程序,具有众多特性,包括支持ACID事务、外键、崩溃修复能力和并发控制。如果对事务的完整性要求比较高,要求实现并发控制,那么选择 InnoDB 存储引擎有很大的优势。如果需要频繁地进行更新、删除数据库的操作,也可以选择 InnoDB 存储引擎,因为该类存储引擎可以实现事务的提交和回滚。
2、MyISAM 存储引擎: 管理非事务表,它提供高速存储和检索,以及全文搜索能力。MyISAM 存储引擎插入数据快,空间和内存使用比较低。如果表主要是用于插入新记录和读出记录,那么选择 MyISAM 存储引擎能实现处理的高效率。如果应用的完整性、并发性要求很低,也可以选择 MyISAM 存储引擎。
3、MEMORY 存储引擎: MEMORY 存储引擎提供 内存中
的表,其所有数据都在内存中,数据的处理速度快,但安全性不高。如果需要很快的读写速度,对数据的安全性要求较低,可以选择 MEMORY 存储引擎。MEMORY 存储引擎对表的大小有要求,不能建太大的表。所以,这类数据库只使用相对较小的数据库表。
ps:以上存储引擎的选择建议是根据不同存储引擎的特点提出的,并不是绝对的。实际应用中还需要根据实际情况进行分析。
三、MySQL 数据类型
数据类型(data_type) 是指系统中所允许的数据的类型。MySQL 数据类型定义了列中可以存储什么数据以及该数据怎样存储的规则。数据库中的每个列都应该有适当的数据类型,用于限制或允许该列中存储的数据。例如,列中存储的为数字,则相应的数据类型应该为数值类型。如果使用错误的数据类型可能会严重影响应用程序的功能和性能,所以在设计表时,应该特别重视数据列所用的数据类型。更改包含数据的列不是一件小事,这样做可能会导致数据丢失。因此,在创建表时必须为每个列设置正确的数据类型和长度。MySQL 支持的数据类型主要分成3类:数字类型、字符串(字符)类型、日期和时间类型。
注意1: 定义字段的数据类型对数据库的优化是十分重要的。
注意2: 下述所有数据类型给出的范围不一定完全准确,仅供参考!
3.1 数字类型
MySQL 持所有的 ANSI/ISO SQL92 数字类型,包括准确数字的数字类型(NUMERIC、DECIMAL、INTEGER 和 SMALLINT) 和近似数字的数字类型(FLOAT、REAL 和 DOUBLE PRECISION)。其中的关键词 INT 是 INTEGER 的同义词,关键词 DEC 是 DECIMAL 的同义词。数字类型总体可以分成整数和浮点两种数据类型,整数数据类型如下表所示:
根据占用字节数可以求出每一种数据类型的取值范围。例如,TINYINT 需要 1 个字节(8bit) 来存储,那么 TINYINT 无符号数的最大值为 28-1,即 255;TINYINT 有符号数的最大值为 27-1,即 127。其他类型的整数的取值范围计算方法相同,如上表所示。
提示:显示宽度和数据类型的取值范围是无关的。显示宽度只是指明 MySQL 最大可能显示的数字个数,数值的位数小于指定的宽度时会由空格填充。如果插入了大于显示宽度的值,只要该值不超过该类型整数的取值范围,数值依然可以插入,而且能够显示出来。例如,year 字段插入 19999,当使用 SELECT 查询该列值的时候,MySQL 显示的将是完整的带有 5 位数字的 19999,而不是 4 位数字的值。其他整型数据类型也可以在定义表结构时指定所需的显示宽度,如果不指定,则系统为每一种类型指定默认的宽度值。
MySQL5.x 版本,设置数据类型为 INT 是有默认宽度的,如下图所示:
早期的 MySQL8.x 版本也是有默认的宽度的,但是最新的 MySQL 没有默认宽度。 如下图所示:
不同的整数类型有不同的取值范围,并且需要不同的存储空间,因此应根据实际需要选择最合适的类型,这样有利于提高查询的效率和节省存储空间。
整数类型可以添加 AUTO_INCREMENT 自增约束条件。UNSIGNED属性:正数的上限提升约1倍。int(M) ,必须和 UNSIGNED ZEROFILL 一起使用才有意义。
应用场景:
- TINYINT:一般用于枚举数据,比如系统设定取值范围很小且固定的场景。
- SMALLINT:可以用于较小范围的统计数据,比如统计工厂的固定资产库存数量等。
- MEDIUMINT:用于较大整数的计算,比如车站每日的客流量等。
- INT、 INTEGER :取值范围足够大,一般情况下不用考虑超限问题,用得最多。比如商品编号。
- BIGINT:只有当你处理特别巨大的整数时才会用到。比如双十一的交易量、大型门户网站点击量、证券公司衍生产品持仓等。
在评估用哪种整数类型的时候,你需要考虑 存储空间 和 可靠性 的平衡问题:一方面,用占用字节数少的整数类型可以节省存储空间;另一方面,要是为了节省存储空间, 使用的整数类型取值范围太小,一旦遇到超出取值范围的情况,就可能引起系统错误 ,影响可靠性。举个例子,商品编号采用的数据类型是 INT 。原因就在于,客户门店中流通的商品种类较多,而且,每天都有旧商品下架,新商品上架,这样不断迭代,日积月累。如果使用 SMALLINT 类型,虽然占用字节数比 INT 类型的整数少,但是却不能保证数据不会超出范围65535。相反,使用 INT ,就能确保有足够大的取值范围,不用担心数据超出范围影响可靠性的问题。在实际工作中, 系统故障产生的成本远远超过增加几个字段存储空间所产生的成本 。 因此,我建议首先确保数据不会超过取值范围,在这个前提之下,再去考虑如何节省存储空间。
浮点类型有两种,分别是 单精度浮点数(FLOAT) 和 双精度浮点数(DOUBLE); 定点类型只有一种,就是 DECIMAL。浮点类型和定点类型都可以用 (M, D)
来表示,其中M称为精度,表示总共的位数;D称为标度,表示小数的位数。浮点数类型的取值范围为 M(1~255)
和 D(1~30)
,且不能大于 M-2),分别表示显示宽度和小数位数。M 和 D 在 FLOAT 和 DOUBLE 中是可选的,FLOAT 和 DOUBLE 类型将被保存为硬件所支持的最大精度。DECIMAL 的默认 D 值为 0、M 值为 10。下表中列出了 MySQL 中的小数类型和存储需求:
DECIMAL 类型不同于 FLOAT 和 DOUBLE。DOUBLE 实际上是以字符串的形式存放的,DECIMAL 可能的最大取值范围与 DOUBLE 相同,但是有效的取值范围由 M 和 D 决定。如果改变 M 而固定 D,则取值范围将随 M 的变大而变大,DECIMAL 的存储空间并不是固定的,而由精度值 M 决定,占用 M+2 个字节。
提示:不论是定点还是浮点类型,如果用户指定的精度超出精度范围,则会四舍五入进行处理。FLOAT 和 DOUBLE 在不指定精度时,默认会按照实际的精度(由计算机硬件和操作系统决定),DECIMAL 如果不指定精度,默认为(10, 0)。
浮点数相对于定点数的优点是在长度一定的情况下,浮点数能够表示更大的范围;缺点是会引起精度问题。
注意:FLOAT 和 DOUBLE 存在误差问题,尽量避免进行浮点数比较。货币等对精度敏感的数据,应该使用 DECIMAL 类型。
3.2 日期和时间类型
日期和时间类型包括 DATE、DATETIME、TIME、TIMESTAMP 和 YEAR。 其中的每种类型都有其取值范围,如赋予它一个不合法的值,将会被 0
代替。日期和时间类型的介绍如下表所示:
在 MySQL 中,日期的顺序是按照标准的 ANSI SQL 格式进行输出的。
3.2.1 补充说明:YEAR 类型
YEAR 类型是一个单字节类型,用于表示年,在存储时只需要 1 个字节。可以使用各种格式指定 YEAR,如下所示:
- 以 4 位字符串或者 4 位数字格式表示的 YEAR,范围为
'1901'~'2155'
。输入格式为YYYY
或者 YYYY,例如,输入'2023'
或2023
,插入数据库的值均为 2023。如下图所示:
- 以 2 位字符串格式表示的 YEAR,范围为
'00' 到 '99'
。'00'~'69'
和'70'~'99'
范围的值分别被转换为 2000~2069 和 1970~1999 范围的 YEAR 值。'0'
与'00'
的作用相同。如下图所示:
- 以 2 位数字表示的 YEAR,范围为 1~99。1~99 和 70~99 范围的值分别被转换为 2001~2069 和 1970~1999 范围的 YEAR 值。注意,在这里 0 值将被转换为 0000,而不是 2000。如下图所示:
3.2.2 补充说明:TIME 类型
TIME 类型用于只需要时间信息的值,在存储时需要 3 个字节。格式为 HH:MM:SS。HH 表示小时,MM 表示分钟,SS 表示秒。TIME 类型的取值范围为 -838:58:59~838:59:59
,小时部分如此大的原因是 TIME 类型不仅可以用于表示一天的时间(必须小于 24 小时),还可能是某个事件过去的时间或两个事件之间的时间间隔(可大于 24 小时,或者甚至为负)。可以使用各种格式指定 TIME 值,如下所示:
'D HH:MM:SS'
格式的字符串。还可以使用这些非严格
的语法:'HH:MM:SS'
、'HH:MM'
、'D HH'
或'SS'
。这里的 D 表示日,可以取 0~34 之间的值。在插入数据库时,D 被转换为小时保存,格式为"D*24+HH"
。如下图所示:
'HHMMSS'
格式、没有间隔符的字符串或者 HHMMSS 格式的数值,假定是有意义的时间。例如,'101112'
被理解为'10:11:12'
,但是'106112'
是不合法的(它有一个没有意义的分钟部分),在存储时将报错。如下图所示:
3.2.3 补充说明:Date 类型
DATE 类型用于仅需要日期值时,没有时间部分,在存储时需要 3 个字节。日期格式为 'YYYY-MM-DD'
,其中 YYYY 表示年,MM 表示月,DD 表示日。在给 DATE 类型的字段赋值时,可以使用字符串类型或者数字类型的数据插入,只要符合 DATE 的日期格式即可。如下所示:
- 以
'YYYY-MM-DD'
或者'YYYYMMDD'
字符中格式表示的日期,取值范围为'1000-01-01'~'9999-12-3'
。例如,输入'2023-01-03'
或者'20230103'
,插入数据库的日期为 20230103。如下图所示:
- 以
'YY-MM-DD'
或者'YYMMDD'
字符串格式表示日期,在这里 YY 表示两位的年值。MySQL 解释两位年值的规则:'00~69'
范围的年值转换为'2000~2069'
,'70~99'
范围的年值转换为'1970~1999'
。例如,输入'23-01-03'
,插入数据库的日期为2023-01-03
;输入'990103'
,插入数据库的日期为1999-01-03
。如下图所示:
- 以 YYMMDD 数字格式表示的日期,与前面相似,00~69 范围的年值转换为 2000~2069,80~99 范围的年值转换为 1980~1999。例如,输入 151231,插入数据库的日期为 2015-12-31,输入 991231,插入数据库的日期为 1999-12-31。如下图所示:
- 使用 CURRENT_DATE 或者 NOW(),插入当前系统日期。如下图所示:
3.2.4 补充说明:DATETIME 类型
DATETIME 类型用于需要同时包含日期和时间信息的值,在存储时需要 8 个字节。日期格式为 'YYYY-MM-DD HH:MM:SS'
,其中 YYYY 表示年,MM 表示月,DD 表示日,HH 表示小时,MM 表示分钟,SS 表示秒。在给 DATETIME 类型的字段赋值时,可以使用字符串类型或者数字类型的数据插入,只要符合 DATETIME 的日期格式即可,如下所示:
- 以
'YYYY-MM-DD HH:MM:SS'
或者'YYYYMMDDHHMMSS'
字符串格式表示的日期,取值范围为'1000-01-01 00:00:00'~'9999-12-3 23:59:59'
。例如,输入'2023-01-03 22:52:05'
或者'20230103225205'
,插入数据库的 DATETIME 值都为2023-01-03 22:52:05
。如下图所示:
- 以
'YY-MM-DD HH:MM:SS'
或者'YYMMDDHHMMSS'
字符串格式表示的日期,在这里 YY 表示两位的年值。与前面相同,'00~79'
范围的年值转换为'2000~2079'
,'80~99'
范围的年值转换为'1980~1999'
。例如,输入'23-01-03 22:52:05'
,插入数据库的 DATETIME 为23-01-03 22:52:05
;输入'230103225205'
,插入数据库的 DATETIME 为23-01-03 22:52:05
,如下图所示:
- 以 YYYYMMDDHHMMSS 或者 YYMMDDHHMMSS 数字格式表示的日期和时间。例如,输入 20230103225205,插入数据库的 DATETIME 为
23-01-03 22:52:05
;输入 230103225205,插入数据库的 DATETIME 为23-01-03 22:52:05
,如下图所示:
3.2.5 补充说明:TIMESTAMP 类型
TIMESTAMP 的显示格式与 DATETIME 相同,显示宽度固定在 19 个字符,日期格式为 YYYY-MM-DD HH:MM:SS,在存储时需要 4 个字节。但是 TIMESTAMP 列的取值范围小于 DATETIME 的取值范围,为 '1970-01-01 00:00:01'UTC~'2038-01-19 03:14:07'UTC
。在插入数据时,要保证在合法的取值范围内。如下图所示:
提示:协调世界时(英:Coordinated Universal Time,法:Temps Universel Coordonné)又称为世界统一时间、世界标准时间、国际协调时间。英文(CUT)和法文(TUC)的缩写不同,作为妥协,简称 UTC。
TIMESTAMP 与 DATETIME 除了存储字节和支持的范围不同外,还有一个最大的区别是:DATETIME 在存储日期数据时,按实际输入的格式存储,即输入什么就存储什么,与时区无关;而 TIMESTAMP 值的存储是以 UTC(世界标准时间)格式保存的,存储时对当前时区进行转换,检索时再转换回当前时区。即查询时,根据当前时区的不同,显示的时间值是不同的。
提示:如果为一个 DATETIME 或 TIMESTAMP 对象分配一个 DATE 值,结果值的时间部分被设置为 ‘00:00:00’,因此 DATE 值未包含时间信息。如果为一个 DATE 对象分配一个 DATETIME 或 TIMESTAMP 值,结果值的时间部分被删除,因此 DATE 值未包含时间信息。
3.3 字符串类型
字符串类型可以分为3类:普通的文本字符串类型(CHAR 和 VARCHAR)、可变类型(TEXT 和 BLOB)和特殊类型(SET 和 ENUM)。
1、普通的文本字符串类型, 即 CHAR 和 VARCHAR 类型,CHAR 列的长度被固定为创建表所声明的长度,取值在1~255;VARCHAR 列的值是变长的字符串,取值和 CHAR 一样。普通的文本字符串类型的介绍如下表所示:
说明:存储字符串长度相同的全部使用 CHAR 类型;字符长度不相同的使用 VARCHAR 类型,不预先分配存储空间,长度不要超过255。
2、可变类型的大小可以改变, TEXT 类型适合存储长文本,而 BLOB 类型适合存储二进制数据,支持任何数据,如文本、声音和图像等。TEXT 和 BLOB 类型的介绍如下表所示:
特殊类型的介绍如下表所示:
提示: BLOB、TEXT、ENUM、SET 字段类型在 MySQL 数据库的检索性能不高,很难使用索引进行优化。如果必须使用这些类型,一般采取特殊的结构设计,或者与程序结合使用其他的字段类型替代。例如,SET 类型可以使用整型 (0,1,2,3....)
、注释功能和程序的检查功能集合替代。
3.4 MySQL 数据类型的选择
MySQL 提供了大量的数据类型,为了优化存储和提高数据库性能,在任何情况下都应该使用最精确的数据类型。前面主要对 MySQL 中的数据类型及其基本特性进行了描述,包括它们能够存放的值的类型和占用空间等。本小节要讨论创建数据库表时如何选择数据类型。可以说字符串类型是通用的数据类型,任何内容都可以保存在字符串中,数字和日期都可以表示成字符串形式。但是也不能把所有的列都定义为字符串类型。 对于数值类型,如果把它们设置为字符串类型的,会使用很多的空间。并且在这种情况下使用数值类型列来存储数字,比使用字符串类型更有效率。另外需要注意的是,由于对数字(日期)和字符串的处理方式不同,查询结果也会存在差异。例如,对数字的排序与对字符串的排序是不一样的。例如,数字 2 小于数字 11,但字符串 '2'
却比字符串 '11'
大,如下图所示:
此问题可以通过把列放到数字上下文中来解决,如下面 SQL 语句:
让 '11'
列加上 0,可以强制列按数字的方式来排序,但这么做很明显是不合理的。如果让 MySQL 把一个字符串列当作一个数字列来对待,会引发很严重的问题。这样做会迫使让列里的每一个值都执行从字符串到数字的转换,操作效率低。而且在计算过程中使用这样的列,会导致 MySQL 不会使用这些列上的任何索引,从而进一步降低查询的速度。所以我们在选择数据类型时要考虑存储、查询和整体性能等方面的问题。在选择数据类型时,首先要考虑这个列存放的值是什么类型的。一般来说,用数值类型列存储数字、用字符类型列存储字符串、用时间类型列存储日期和时间。
1、数值类型。 对于数值类型列,如果要存储的数字是整数(没有小数部分),则使用整数类型;如果要存储的数字是小数(带有小数部分),则可以选用 DECIMAL 或浮点类型,但是一般选择 FLOAT 类型(浮点类型的一种)。例如,
- 如果列的取值范围是
1~99999
之间的整数,则 MEDIUMINT UNSIGNED 类型是最好的选择。MEDIUMINT 是整数类型,UNSIGNED 用来将数字类型无符号化。比如 INT 类型的取值范围是-2147483648 ~ 2147483647
,那么 INT UNSIGNED 类型的取值范围就是0~ 4294967295
。 - 如果需要存储某些整数值,则值的范围决定了可选用的数据类型。如果取值范围是
0~1000
,那么可以选择 SMALLINT~BIGINT 之间的任何一种类型。如果取值范围超过了 200 万,则不能使用 SMALLINT,可以选择的类型变为从 MEDIUMINT 到 BIGINT 之间的某一种。当然,完全可以为要存储的值选择一种 最大 的数据类型。但是,如果正确选择数据类型,不仅可以使表的存储空间变小,也会提高性能。因为与较长的列相比,较短的列的处理速度更快。当读取较短的值时,所需的磁盘读写操作会更少,并且可以把更多的键值放入内存索引缓冲区里。如果无法获知各种可能值的范围,则只能靠猜测,或者使用 BIGINT 以满足最坏情况的需要。如果猜测的类型偏小,那么也不是就无药可救。将来,还可以使用 ALTER TABLE 让该列变得更大些。 - 如果数值类型需要存储的数据为货币,如人民币。在计算时,使用到的值常带有元和分两个部分。它们看起来像是浮点值,但 FLOAT 和 DOUBLE 类型都存在四舍五入的误差问题,因此不太适合。因为人们对自己的金钱都很敏感,所以需要一个可以提供完美精度的数据类型。可以把货币表示成
DECIMAL(M,2)
类型,其中 M 为所需取值范围的最大宽度。这种类型的数值可以精确到小数点后 2 位。DECIMAL 的优点在于不存在舍入误差,计算是精确的。 - 对于电话号码、信用卡号和社会保险号都会使用非数字字符。因为空格和短划线不能直接存储到数字类型列里,除非去掉其中的非数字字符。但即使去掉了其中的非数字字符,也不能把它们存储成数值类型,以避免丢失开头的 零。
2、日期和时间类型。 MySQL 对于不同种类的日期和时间都提供了数据类型,比如 YEAR 和 TIME。如果只需要记录年份,则使用 YEAR 类型即可;如果只记录时间,可以使用 TIME 类型。如果同时需要记录日期和时间,则可以使用 TIMESTAMP 或者 DATETIME 类型。由于TIMESTAMP 列的取值范围小于 DATETIME 的取值范围,因此存储较大的日期最好使用 DATETIME。TIMESTAMP 也有一个 DATETIME 不具备的属性。默认情况下,当插入一条记录但并没有指定 TIMESTAMP 这个列值时,MySQL 会把 TIMESTAMP 列设为当前的时间。因此当需要插入记录和当前时间时,使用 TIMESTAMP 是方便的,另外 TIMESTAMP 在空间上比 DATETIME 更有效。
MySQL 没有提供时间部分为可选的日期类型。DATE 没有时间部分,DATETIME 必须有时间部分。如果时间部分是可选的,那么可以使用 DATE 列来记录日期,再用一个单独的 TIME 列来记录时间。然后,设置 TIME 列可以为 NULL。SQL 语句如下:
CREATE TABLE mytb1 (
date DATE NOT NULL, #日期是必需的
time TIME NULL #时间可选(可能为NULL)
);
3、字符串类型。 字符串类型没有像数字类型列那样的 取值范围
,但它们都有长度的概念。如果需要存储的字符串短于 256 个字符,那么可以使用 CHAR、VARCHAR 或 TINYTEXT。如果需要存储更长一点的字符串,则可以选用 VARCHAR 或某种更长的 TEXT 类型。如果某个字符串列用于表示某种固定集合的值,那么可以考虑使用数据类型 ENUM 或 SET。CHAR 和 VARCHAR 之间的特点和选择, CHAR 和 VARCHAR 的区别如下:
- CHAR 是固定长度字符,VARCHAR 是可变长度字符。
- CHAR 会自动删除插入数据的尾部空格,VARCHAR 不会删除尾部空格。
CHAR 是固定长度,所以它的处理速度比 VARCHAR 的速度要快,但是它的缺点就是浪费存储空间。所以对存储不大,但在速度上有要求的可以使用 CHAR 类型,反之可以使用 VARCHAR 类型来实现。
存储引擎对于选择 CHAR 和 VARCHAR 的影响:
- 对于 MyISAM 存储引擎,最好使用固定长度的数据列代替可变长度的数据列。这样可以使整个表静态化,从而使数据检索更快,用空间换时间。
- 对于 InnoDB 存储引擎,最好使用可变长度的数据列,因为 InnoDB 数据表的存储格式不分固定长度和可变长度,因此使用 CHAR 不一定比使用 VARCHAR 更好,但由于 VARCHAR 是按照实际的长度存储,比较节省空间,所以对磁盘 I/O 和数据存储总量比较好。
ENUM 和 SET: ENUM 只能取单值,它的数据列表是一个枚举集合。它的合法取值列表最多允许有 65535个成员。因此,在需要从多个值中选取一个时,可以使用 ENUM。比如,性别字段适合定义,为 ENUM 类型,每次只能从 男 或 女 中取一个值。SET 可取多值。它的合法取值列表最多允许有 64 个成员。空字符串也是一个合法的 SET 值。在需要取多个值的时候,适合使用 SET 类型,比如,要存储一个人兴趣爱好,最好使用 SET 类型。ENUM 和 SET 的值是以字符串形式出现的,但在内部,MySQL 以数值的形式存储它们。
二进制类型: BLOB 是二进制字符串,TEXT 是非二进制字符串,两者均可存放大容量的信息。BLOB 主要存储图片、音频信息等,而 TEXT 只能存储纯文本文件。
小结:本文对 MySQL 存储引擎和数据类型进行了详细讲解,并通过举例说明,帮助读者更好地理解所学知识的用法。在阅读本文时,读者应该重点对 MySQL 中的数据类型进行掌握,在以后设计数据表时,能够合理地选择所使用的数据类型,同时掌握如何选择存储引擎(以后是需要重点了解和学习的),初学时可以初步了解大概有个印象即可。
至此今天的学习就到此结束了,笔者在这里声明,笔者写文章只是为了学习交流,以及让更多学习数据库的读者少走一些弯路,节省时间,并不用做其他用途,如有侵权,联系博主删除即可。感谢您阅读本篇博文,希望本文能成为您编程路上的领航者。祝您阅读愉快!
好书不厌读百回,熟读课思子自知。而我想要成为全场最靓的仔,就必须坚持通过学习来获取更多知识,用知识改变命运,用博客见证成长,用行动证明我在努力。
如果我的博客对你有帮助、如果你喜欢我的博客内容,请点赞
、评论
、收藏
一键三连哦!听说点赞的人运气不会太差,每一天都会元气满满呦!如果实在要白嫖的话,那祝你开心每一天,欢迎常来我博客看看。
编码不易,大家的支持就是我坚持下去的动力。点赞后不要忘了关注
我哦!