每天学习一点点之 MySQL TINYINT

news2024/11/16 7:53:23

我已经不是第一次遇到关于 TINYINT 的问题了。在 MySQL 中,当我们将某个字段设置为 TINYINT,随着业务的扩展,我们可能会发现 TINYINT 的范围无法满足需求。这时需要修改字段属性。但如果表的数据量很大,或者由于分表导致涉及的表数量众多,这个过程可能会变得比较复杂。更糟糕的是,如果代码中的数据类型为 int,而 MySQL 中的数据类型为 TINYINT,可能会导致存储异常数据。

这里把 MySQL 整数类型做个总结:

类型名称翻译空间占用范围(有符号)范围(无符号)
TINYINT很小的整数1个字节-128〜1270 〜255
SMALLINT小的整数2个宇节-32768〜327670〜65535
MEDIUMINT中等大小的整数3个字节-8388608〜83886070〜16777215
INT (INTEGHR)普通大小的整数4个字节-2147483648〜21474836470〜4294967295
BIGINT大整数8个字节-9223372036854775808〜92233720368547758070〜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

可以得出如下结论:

  1. TINYINT 转换为 Integer

    在 MySQL 中,TINYINT 是一个 8 位的整数,可以是有符号的(取值范围 -128 到 127)或无符号的(取值范围 0 到 255)。在 Java 中最接近的类型是 byte,也是 8 位的,但它是有符号的,取值范围是 -128 到 127。这意味着 TINYINT 的取值范围可能超过了 Java Byte 类型的取值范围。因此,JDBC 默认将 TINYINT 类型转换为 Java 的 Integer 类型,而不是 Byte 类型

  2. 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) 中找到:

 @Override
    public Object getObject(int columnIndex) throws SQLException {
        ...
        Field field = this.columnDefinition.getFields()[columnIndexMinusOne];
        switch (field.getMysqlType()) {
            //TINYINT(1)转化为 BIT
            case 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 转化为 Integer
            case 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

存储空间逐渐变大,而性能却逐渐变小

存储空间和性能之间的关系可以从两个方面来理解:

  1. 存储空间:TINYINTSMALLINTMEDIUMINTINTBIGINT 这些类型的存储空间从小到大排列。这是因为它们能表示的数值范围也是从小到大的。例如,TINYINT 只需要 1 字节就可以表示 -128 到 127 的整数,而 BIGINT 需要 8 字节来表示更大范围的整数。

  2. 性能:当我们说性能逐渐变小,我们是指处理更大的数据类型通常需要更多的 CPU 时间和内存。例如,读取和写入一个 BIGINT 值通常会比读取和写入一个 TINYINT 值需要更多的时间。这是因为处理更大的数据需要更多的计算资源。

    但这些不同的整数类型在性能上的差异是微不足道的。这是因为现代的 CPU 和内存都足够快了。

References

  • MySQL开发规范(内网)

欢迎关注公众号:
在这里插入图片描述

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

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

相关文章

AI虚拟数字人——营销宣传领域的新亮点

AI生活节即将到来,邀请消费者共同探索生活小妙趣,为美好生活注入新的想象。AI一词我们过去可能听的比较多,听到最多的可能就是AI虚拟数字人了。这年头,打造一个AI主播、虚拟数字人已经屡见不鲜了,因为AI数字人拥有强大…

数字孪生3D场景开发工具:弥补不足,开拓全新可能

随着数字化时代的来临,越来越多的企业和行业开始探索数字孪生技术的应用。数字孪生是指通过数字技术将现实世界中的物体、场景等复制到虚拟世界中,以实现实时监测、预测和优化。然而,在数字孪生的发展过程中,一些不足也逐渐浮现。…

AndroidStudio - 新版本 Logcat 使用详解

最近这俩天正好有时间给自己做一下减法,忘记是去年还是今年,在升级 AndroidStudio 后使用 Logcat查看日志的方式也发生了一些变化,虽然一直在使用,但每当看到之前还未关闭 Logcat 命令行工具额昂也,就感觉可能还存在知…

基于springboot的社区团购系统设计

摘 要 本课题是根据用户的需要以及网络的优势建立的一个社区团购系统,来满足用户团购的需求。 本社区团购系统应用Java技术,MYSQL数据库存储数据,基于Spring Boot框架开发。在网站的整个开发过程中,首先对系统进行了需求分析&…

手持机|三防智能手机_4寸/5寸/6寸安卓系统三防手机PDA手持终端方案

随着科技的不断发展,三防手持机作为一种多功能设备,正逐渐在各行业得到广泛应用。这款手持机采用高性能处理器,支持高精度北斗定位和工业本安防爆功能,并具备IP67级防水防尘性能和1.5米防跌落能力。因此,它在仓储管理、…

C语言进阶之笔试题详解(2)

前言 这里的内容包括二维数组笔试题和指针笔试题,供给读者对这部分知识进行加深和巩固。 ✨ 猪巴戒:个人主页✨ 所属专栏:《C语言进阶》 🎈跟着猪巴戒,一起学习C语言🎈 目录 前言 笔试题 二维数组 题目…

nvm 下载node时候下载不到npm包的解决方法

个人博客链接 公众号-nvm 下载node时候下载不到npm包的解决方法 求关注 可以跳过的背景 最近项目比较有空,所以就可以有时间写一些demo,主要测试下react的一些语法,毕竟自己上次写react已经是22年的7月份了,期间对于react-router等的hook…

差分阻抗90Ω±10%或者其他分别走什么阻抗

差分阻抗90Ω10%或者其他分别走什么阻抗 普通走线阻抗HDMI接口布线要求USB接口布线要求网口接口布线要求LCD 接口布线要求DDR3关键信号处理要点 普通走线阻抗 必须选择 PCB 走线阻抗来匹配使用中的所有逻辑系别的特性阻抗(对于 CMOS 和 TTL,特性阻抗的范围是 80~11…

Java 多线程循环打印

文章目录 一、标志变量 互斥锁二、标志变量 synchronized三、标志变量 互斥锁 条件变量四、原子变量五、信号量 一、标志变量 互斥锁 标志变量用于标识当前应该是哪个线程进行输出,互斥锁用于保证对标志变量的互斥访问。 public class Main {private static …

分享常见msvcp140.dll丢失的解决方法,msvcp140.dll修复的问题

在使用电脑的过程中可能会出现关于msvcp140.dll丢失的问题,通常出现这样的问题都会导致电脑中的程序出现不能正常运行的情况。并且如果不及时将msvcp140.dll修复的话可能还会导致电脑出现其他的问题。这篇文章就将给大家介绍关于msvcp140.dll丢失的解决方法。 一.常…

美国第三季度经济GDP数据亮眼,其增长率上修至近2年最快

KlipC报道:美国商务部公布美国第三季度GDP按年率增长5.2%,较首次预估数据上调了0.3%。也是近2年来最快增速。 KlipC的分析师表示:“相较于第二季度相比,第三季度的时机GDP主要反映了消费者指出和私人库存投资的加速和出口的上升。…

Prosys OPC Client连接OPC DA

Prosys OPC Client连接OPC DA Prosys OPC 客户端将帮助排除 OPC 连接故障并测试 OPC 服务器。 您可以读写数据、浏览服务器以及导出和导入地址空间。 OPC 客户端轻巧、快速且易于使用。 支持 OPC DA 1.0a 和 OPC DA 2.05a 官方地址: https://www.prosysopc.com/products/opc-…

XUbuntu22.04之安装OBS30.0强大录屏工具(一百九十五)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒…

颜色十六进制代码对照表

白色 #FFFFFF 2 红色 #FF0000 3 绿色 #00FF00 蓝色 #0000FF 5 牡丹红 #FF00FF 6 青色 #00FFFF 黄色 #FFFF00 8 黑色 #000000 9 海蓝 #70DB93 巧克力色 #5C3317 11 蓝紫色 #9F5F9F 12 黄铜色 #B5A642 亮金色 #D9D919 14 棕色 #A67D3D 15 青铜色 #8C7853 2号青铜色 #A67D3D 17 士…

基于SSM搭建系统

原理 SSM集成 SpringSpringMvcMybatis集成 框架集成核心,如果你的项目中,用到了Spring框架,那么其他框架主要就是和Spring集成; 和Spring集成的核心思路: 把当前框架的核心类,交给Spring管理&#xff08…

C++: string的模拟实现

C: string的模拟实现 一.前置说明1.模拟实现string容器的目的2.我们要实现的大致框架 二.默认成员函数1.构造函数2.拷贝构造函数1.传统写法2.现代写法 3.析构函数4.赋值运算符重载1.传统写法2.现代写法 三.遍历和访问1.operator[]运算符重载2.iterator迭代器 四.容量相关函数1.…

ant design vue3 处理 ant-card-head ant-tabs靠左边对齐之has选择器不生效

火狐浏览器是不支持has的。 解决方法:通过position来解决。

拥抱未来:大语言模型解锁平台工程的无限可能

01 了解大型语言模型 (LLM) 大型语言模型(LLM)是一种人工智能(AI)算法,它使用深度学习技术和海量数据集来理解、总结、生成和预测新内容。凭借合成大量信息的能力,LLM 可以提高以前需要人类专家的业务流程的…

2002-2021年全国各省产业结构合理化高级化指数数据(含原始数据+计算过程+计算结果)

2002-2021年全国各省产业结构合理化高级化指数数据(含原始数据计算过程计算结果) 1、时间:2002-2021年 2、指标:地区、时间、就业总人数(万人)、第一产业就业人数(万人)、第二产业…

C语言从入门到实战——常用字符函数和字符串函数的了解和模拟实现

常用字符函数和字符串函数的了解和模拟实现 前言1. 字符分类函数2. 字符转换函数3. strlen的使用和模拟实现4. strcpy的使用和模拟实现5. strcat的使用和模拟实现6. strcmp的使用和模拟实现7. strncpy函数的使用8. strncat函数的使用9. strncmp函数的使用10. strstr的使用和模拟…