每天学习一点点之 MySQL TINYINT
我已经不是第一次遇到关于 TINYINT
的问题了。在 MySQL 中,当我们将某个字段设置为 TINYINT
,随着业务的扩展,我们可能会发现 TINYINT
的范围无法满足需求。这时需要修改字段属性。但如果表的数据量很大,或者由于分表导致涉及的表数量众多,这个过程可能会变得比较复杂。更糟糕的是,如果代码中的数据类型为 int
,而 MySQL 中的数据类型为 TINYINT
,可能会导致存储异常数据。
这里把 MySQL 整数类型做个总结:
类型名称 | 翻译 | 空间占用 | 范围(有符号) | 范围(无符号) |
---|---|---|---|---|
TINYINT | 很小的整数 | 1个字节 | -128〜127 | 0 〜255 |
SMALLINT | 小的整数 | 2个宇节 | -32768〜32767 | 0〜65535 |
MEDIUMINT | 中等大小的整数 | 3个字节 | -8388608〜8388607 | 0〜16777215 |
INT (INTEGHR) | 普通大小的整数 | 4个字节 | -2147483648〜2147483647 | 0〜4294967295 |
BIGINT | 大整数 | 8个字节 | -9223372036854775808〜9223372036854775807 | 0〜18446744073709551615 |
TINYINT 与 INT:空间节省的实际影响
如上表所示,使用 TINYINT
替代 INT
可以节省 3 字节的存储空间。
换句话说,如果你有一个包含 1,000,000 行的表,并且其中有一个 INT
类型的列。将此列更改为 TINYINT
,将大约节省 3MB 的存储空间(1,000,000 行 * 3 字节/行 = 3,000,000 字节 ≈ 3MB)。但这种节省在大多数情况下可能并不会带来显著的性能提升或成本降低。
何时应考虑使用 TINYINT
对于这个问题,我认为没有必要过于纠结,也没有绝对的答案。
有时候,我们选择使用 TINYINT
主要是出于教条式的成本考虑,但如前所述,这种成本差异几乎可以忽略。因此,决定何时使用 TINYINT
,我们只需要考虑其范围是否满足当前业务需求以及可能的未来发展。
例如,如果你需要添加一个表示性别或者 true
/false
的字段,这种情况下,数据范围较小,且不可能超过 TINYINT
的范围,那么使用 TINYINT
是合适的。然而,对于如订单来源或状态等可能会发生变化的字段,我们需要更加谨慎,因为这些场景是典型的随着业务的发展可能会修改 TINYINT
字段的情况,这也是我在实际工作中遇到的最常见的场景。
解读公司内部《MySQL开发规范》
公司内部的《MySQL开发规范》 中有这么一段说明:
禁止使用tinyint ,在JAVA环境有转换问题。区分使用TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT数据类型和取值范围(TINYINT>SMALLINT>MEDIUMINT>INT>BIGINT>DECIMAL—存储空间逐渐变大,而性能却逐渐变小)。
禁止使用 TINYINT
这个问题的关键在于 MySQL 中的 TINYINT
类型和 Java 中的数据类型之间的映射关系。
先看一个例子:
package blog.dongguabai.others.mysql_tinyint;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;/*** @author dongguabai* @date 2023-11-30 00:27*/
public class Test {public static String url = "jdbc:mysql://10.224.221.151:3306/test_1";public static String user = "root";public static String password = "root";public static void main(String[] args) {try (Connection conn = DriverManager.getConnection(url, user, password);Statement stmt = conn.createStatement()) {stmt.execute("DROP TABLE IF EXISTS tinyint_test");stmt.execute("CREATE TABLE tinyint_test (id TINYINT UNSIGNED, id_signed TINYINT, id_boolean TINYINT(1))");stmt.execute("INSERT INTO tinyint_test VALUES (255, -128, 1)");try (ResultSet rs = stmt.executeQuery("SELECT * FROM tinyint_test")) {while (rs.next()) {System.out.println("id: " + rs.getObject("id").getClass().getName());System.out.println("id_signed: " + rs.getObject("id_signed").getClass().getName());System.out.println("id_boolean: " + rs.getObject("id_boolean").getClass().getName());}}} catch (SQLException e) {e.printStackTrace();}}
}
输出结果:
id: java.lang.Integer
id_signed: java.lang.Integer
id_boolean: java.lang.Boolean
可以得出如下结论:
-
TINYINT
转换为Integer
在 MySQL 中,
TINYINT
是一个 8 位的整数,可以是有符号的(取值范围 -128 到 127)或无符号的(取值范围 0 到 255)。在 Java 中最接近的类型是byte
,也是 8 位的,但它是有符号的,取值范围是 -128 到 127。这意味着TINYINT
的取值范围可能超过了 JavaByte
类型的取值范围。因此,JDBC 默认将TINYINT
类型转换为 Java 的Integer
类型,而不是Byte
类型 -
TINYINT(1)
转换为Boolean
在 MySQL 中,
TINYINT(1)
通常用于表示布尔值,JDBC 将其转换为 Java 的Boolean
类型。(可以在 JDBC 连接字符串中添加
tinyInt1isBit=false
参数,这样TINYINT(1)
就不会被转换为Boolean
,而是和其他TINYINT
类型一样被转换为Integer
)
原理可以从 com.mysql.cj.jdbc.result.ResultSetImpl#getObject(int)
中找到:
@Overridepublic Object getObject(int columnIndex) throws SQLException {...Field field = this.columnDefinition.getFields()[columnIndexMinusOne];switch (field.getMysqlType()) {//TINYINT(1)转化为 BITcase BIT:// TODO Field sets binary and blob flags if the length of BIT field is > 1; is it needed at all?if (field.isBinary() || field.isBlob()) {byte[] data = getBytes(columnIndex);if (this.connection.getPropertySet().getBooleanProperty(PropertyKey.autoDeserialize).getValue()) {Object obj = data;if ((data != null) && (data.length >= 2)) {if ((data[0] == -84) && (data[1] == -19)) {// Serialized object?try {ByteArrayInputStream bytesIn = new ByteArrayInputStream(data);ObjectInputStream objIn = new ObjectInputStream(bytesIn);obj = objIn.readObject();objIn.close();bytesIn.close();} catch (ClassNotFoundException cnfe) {throw SQLError.createSQLException(Messages.getString("ResultSet.Class_not_found___91") + cnfe.toString()+ Messages.getString("ResultSet._while_reading_serialized_object_92"), getExceptionInterceptor());} catch (IOException ex) {obj = data; // not serialized?}} else {return getString(columnIndex);}}return obj;}return data;}return field.isSingleBit() ? Boolean.valueOf(getBoolean(columnIndex)) : getBytes(columnIndex);case BOOLEAN:return Boolean.valueOf(getBoolean(columnIndex));//TINYINT 转化为 Integercase TINYINT:return Integer.valueOf(getByte(columnIndex));case TINYINT_UNSIGNED:case SMALLINT:case SMALLINT_UNSIGNED:case MEDIUMINT:case MEDIUMINT_UNSIGNED:case INT:return Integer.valueOf(getInt(columnIndex)); //TINYINT_UNSIGNED 转化为 Integer
...
}
这里要注意数据库字段设置为 TINYINT(1)
在 columnDefinition
会被映射为 MysqlType.BIT
。
存储空间逐渐变大,而性能却逐渐变小
存储空间和性能之间的关系可以从两个方面来理解:
-
存储空间:
TINYINT
、SMALLINT
、MEDIUMINT
、INT
和BIGINT
这些类型的存储空间从小到大排列。这是因为它们能表示的数值范围也是从小到大的。例如,TINYINT
只需要 1 字节就可以表示 -128 到 127 的整数,而BIGINT
需要 8 字节来表示更大范围的整数。 -
性能:当我们说性能逐渐变小,我们是指处理更大的数据类型通常需要更多的 CPU 时间和内存。例如,读取和写入一个
BIGINT
值通常会比读取和写入一个TINYINT
值需要更多的时间。这是因为处理更大的数据需要更多的计算资源。但这些不同的整数类型在性能上的差异是微不足道的。这是因为现代的 CPU 和内存都足够快了。
References
- MySQL开发规范(内网)
欢迎关注公众号:
相关文章:

每天学习一点点之 MySQL TINYINT
我已经不是第一次遇到关于 TINYINT 的问题了。在 MySQL 中,当我们将某个字段设置为 TINYINT,随着业务的扩展,我们可能会发现 TINYINT 的范围无法满足需求。这时需要修改字段属性。但如果表的数据量很大,或者由于分表导致涉及的表数…...
【数据集】未来不同情景下预测数据:如人口、土地利用等
未来不同情景下预测数据:如人口、土地利用等 1 人口数据1.1 Global One-Eighth Degree Population Base Year and Projection Grids Based on the SSPs, v1.01 (2000 – 2100)数据介绍数据下载1.2 Global dataset of gridded population and GDP scenarios数据介绍数据下载2…...

TDA4VM EVM开发板调试笔记
文章目录 1. 前言2. 官网资料导读3. 安装 Linux SDK4. 制作SD 启动卡5. 验证启动1. 前言 TDA4作为一般经典的车规级SOC芯片,基于它的低阶智驾方案目前成为各家智驾方案公司的量产首选,这也使得基于TDA4的开发需求陡增,开发和使用TDA4既要熟悉Linux驱应用开发,还要熟悉传统…...
项目里边更换了同名的图片地址 / 图片没有及时更新 / 什么原因
一、问题分析 1.1、分析一 浏览器缓存 项目里边更换了同名的图片地址,图片没有及时更新 可能是浏览器缓存的原因,浏览器会将之前访问过的文件缓存下来,下次访问同名的文件时会先从缓存中读取。 如果相同的图片地址没有发生变化,…...

RandomAccessFile学习笔记
文章目录 RandomAccessFile学习笔记前言1、RandomAccessFile基本介绍1.1 RandomAccessFile相关基本概念1.2 RandomAccessFile家族体系 2、RandomAccessFile基本使用2.1 RandomAccessFile常用API介绍2.2 RandomAccessFile常用API演示2.3 RandomAccessFile实现断点续传 RandomAcc…...

主流数据库类型总结
前言:随着互联网的高速发展,为了满足不同的应用场景,数据库的种类越来越多容易混淆,所以有必要在此总结一下。数据库根据数据结构可分为关系型数据库和非关系型数据库。非关系型数据库中根据应用场景又可分为键值(Key-…...

程序员养生之道
程序员养生之道——如何保持健康的生活方式 摘要: 随着互联网行业的快速发展,越来越多的人选择从事程序员这个职业。然而,长时间的工作和高强度的压力容易导致程序员出现亚健康状况,如头发稀疏、视力下降、肥胖等问题。因此&#…...

CNN对 MNIST 数据库中的图像进行分类
加载 MNIST 数据库 MNIST 是机器学习领域最著名的数据集之一。 它有 70,000 张手写数字图像 - 下载非常简单 - 图像尺寸为 28x28 - 灰度图 from keras.datasets import mnist# 使用 Keras 导入MNIST 数据库 (X_train, y_train), (X_test, y_test) mnist.load_data()print(&…...
HarmonyOS开发工具简介
工具简介 更新时间: 2023-10-13 11:06 分享 添加收藏 说明 该文档匹配DevEco Studio 3.1.1 Release版本。 概述 HUAWEI DevEco Studio(获取工具请单击链接下载,以下简称DevEco Studio)是基于IntelliJ IDEA Community开源版本打造,…...

大量索引场景下 Easysearch 和 Elasticsearch 的吞吐量差异
最近有客户在使用 Elasticsearch 搜索服务时发现集群有掉节点,并且有 master 收集节点信息超时的日志,节点的负载也很高,不只是 data 节点,master 和协调节点的 cpu 使用率都很高,看现象集群似乎遇到了性能瓶颈。 查看…...

东明石化集团领导团队参访震坤行工业超市
东明石化集团领导团队参访震坤行工业超市 10月16日,山东东明石化集团(以下简称东明石化)总裁李治先生一行带队来访参观交流震坤行,与震坤行工业超市董事长兼CEO陈龙、销售负责团队开展座谈。期间,双方就企业数字化转型…...
Java常见的面试题(很基础那种)
这里介绍一下,一些比较基础的Java面试题,比较适合应届生、实习生这些朋友。因为对于刚出来工作的Java工程师,很多企业都偏向招一些基础比较好的苗子回来培养。所以啊,在校的朋友们,一定要在读书期间,多做项目,如果没有实际的项目,可以在github找一些案例来做参考,先模…...

MySQL处理并发访问和高负载的关键技术和策略
我深知在数据库管理中处理并发访问和高负载的重要性。在这篇文章中,我将探讨MySQL处理并发访问和高负载的关键技术和策略,以帮助读者更好地优化数据库性能。 图片来源:MySQL处理并发访问和高负载的关键技术和策略 MySQL数据库在处理并发访问…...

软件测试jmeter基本使用
1安装与配置 1.jdk下载 下载地址:https://www.oracle.com/java/technologies/downloads/#jdk18-windows(压缩包中会给) 2.jmeter下载 Apache JMeter - Download Apache JMeter(压缩包中有) 3.操作教学 打开软件后新…...

一文讲透Python函数中的局部变量和全局变量
变量的作用域就是变量能够发挥作用的区域,超出既定区域后就无法发挥作用。根据变量的作用域可以将变量分为局部变量和全局变量。 1.局部变量 局部变量是在函数内部定义并使用的变量,也就是说只有在函数内部,在函数运行时才会有效࿰…...

【LeetCode】每日一题 2023_11_23 HTML 实体解析器(调库/打工)
文章目录 刷题前唠嗑题目:HTML 实体解析器题目描述代码与解题思路 结语 刷题前唠嗑 题目:HTML 实体解析器 题目链接:1410. HTML 实体解析器 题目描述 代码与解题思路 func entityParser(s string) (ans string) {return strings.NewRepla…...

Flask SocketIO 实现动态绘图
Flask-SocketIO 是基于 Flask 的一个扩展,用于简化在 Flask 应用中集成 WebSocket 功能。WebSocket 是一种在客户端和服务器之间实现实时双向通信的协议,常用于实现实时性要求较高的应用,如聊天应用、实时通知等,使得开发者可以更…...

软著项目推荐 深度学习 植物识别算法系统
文章目录 0 前言2 相关技术2.1 VGG-Net模型2.2 VGG-Net在植物识别的优势(1) 卷积核,池化核大小固定(2) 特征提取更全面(3) 网络训练误差收敛速度较快 3 VGG-Net的搭建3.1 Tornado简介(1) 优势(2) 关键代码 4 Inception V3 神经网络4.1 网络结构 5 开始训练5.1 数据集…...
自动驾驶HWP 功能规范
目 录 概述 1 目的 1范围 1术语及缩写 1设计与实验标准 1 设计标准 2设计标准执行优先顺序 2功能规范 Specification 4 功能描述 Functional Description 4 工作条件与应用范围 Application Scope 4道路交通 4天气与光线 4传感器方案及需求 5 驾驶员状态监控系统 5前视摄像…...

Ubuntu 环境下 NFS 服务安装及配置使用
需求:公司内部有多台物理服务器,需要A服务器上的文件让B服务器访问,也就是两台服务器共享文件,当然也可以对A服务器上的文件做权限管理,让B服务器只读或者可读可写 1、NFS 介绍 NFS 是 Network FileSystem 的缩写&…...
谷歌浏览器插件
项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...
云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?
大家好,欢迎来到《云原生核心技术》系列的第七篇! 在上一篇,我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在,我们就像一个拥有了一块崭新数字土地的农场主,是时…...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...

微信小程序 - 手机震动
一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注:文档 https://developers.weixin.qq…...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...
ffmpeg(四):滤镜命令
FFmpeg 的滤镜命令是用于音视频处理中的强大工具,可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下: ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜: ffmpeg…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解
JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用,结合SQLite数据库实现联系人管理功能,并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能,同时可以最小化到系统…...

MySQL:分区的基本使用
目录 一、什么是分区二、有什么作用三、分类四、创建分区五、删除分区 一、什么是分区 MySQL 分区(Partitioning)是一种将单张表的数据逻辑上拆分成多个物理部分的技术。这些物理部分(分区)可以独立存储、管理和优化,…...
LOOI机器人的技术实现解析:从手势识别到边缘检测
LOOI机器人作为一款创新的AI硬件产品,通过将智能手机转变为具有情感交互能力的桌面机器人,展示了前沿AI技术与传统硬件设计的完美结合。作为AI与玩具领域的专家,我将全面解析LOOI的技术实现架构,特别是其手势识别、物体识别和环境…...