MySQL数据库中的浮点类型和高精度类型有什么区别?为什么不推荐使用浮点类型?

本文主要是介绍MySQL数据库中的浮点类型和高精度类型有什么区别?为什么不推荐使用浮点类型?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在软件开发中,作为后端,无可避免的需要熟练使用 MySQL 数据库进行数据存储和读取。对于信息系统而言,数据库的的地位不言而喻。那作为软件开发工程师,在使用 MySQL 过程中,又有哪些需要注意的呢?我们从实际开发来一点点的介绍。

本篇文章,我们先来了解一下关于数据库数字类型的一些内容。我们在做表设计的时候,数字类型是常见的数据类型,用于存储数字相关的信息(整数型、浮点型、高精度型)。但是在不同的业务场景中,错误的使用数字类型,也会给系统带来很大的风险。

一、数字类型

1、整数类型

MySQL 数据库支持 SQL 标准支持的整型类型:INT、SMALLINT。此外,MySQL 数据库也支持诸如 TINYINT、MEDIUMINT 和 BIGINT 整型类型。我们来看一下各整型所占用的存储空间及取值范围:

类型占用空间最小值-最大值(signed)最小值-最大值(unsigned)
TINYINT1-128~1270~255
SMALLINT2-32768~327680~65535
MEDIUMINT3-8388608~83886070~16777215
INT4-2147483648~21474836470~4294967295
BIGINT8-9223372036854775808~92233720368547758070~18446744073709551615

在整型数字类型中,有 signed 和 unsigned 的属性,表示的是整型的取值范围。默认是 signed。我们在设计时,建议不要刻意去用 unsigned 属性,因为在做数据分析时,SQL 可能会返回不是理想的结果。

2、浮点类型和高精度类型

MySQL 的数字类型中,除了上面说的整数类型,还有浮点型和高精度型。

MySQL 之前的版本中存在浮点类型 Float 和 Double,但这些类型因为不是高精度,也不是 SQL 标准的类型,所以在真实的生产环境中不推荐使用,否则在计算时,由于精度类型问题,会导致最终的计算结果出错。

更重要的是,在 MySQL8.0.17 版本开始,如果我们建表继续使用 FLOAT 和 DOUBLE,则会抛出警告:

Specifying number of digits for floating point data types is deprecated and will be removed in a future release

数字类型中的高精度 DECIMAL 类型可以使用,在设置字段为 DECIMAL 类型时,需要指定精度和标度。例如:

count DECIMAL(6,4)

其中,6 是精度(精度表示保存值的主要位数),4 是标度(标度表示小数点后面保存的位数)。通常在表结构设计中,类型 DECIMAL 可以用来表示用户的工程款项、账户的余额等精确到小数点后 4 位的业务。

然而,在海量并发的互联网业务中使用,金额字段的设计并不推荐使用 DECIMAL 类型,而更推荐使用 INT 整型类型。

二、表结构设计实战

1、整型与主键自增设计

在真实业务场景中,整型类型最常见的就是在业务中用来表示某件物品的数量。例如销售数量,或电商中的库存数量、购买次数等。在业务中,整型类型的另一个常见且重要的使用用法是作为表的主键,即用来唯一标识一行数据。

整型结合属性 auto_increment,可以实现自增功能,但在表结构设计时用自增做主键,特别要注意以下两点,若不注意,可能会对业务造成灾难性的打击:

  • 用 BIGINT 做主键,而不是 INT;

  • 自增值并不持久化,可能会有回溯现象(MySQL 8.0 版本前)。

从上述的类型对比中可以发现,INT 的最大范围在 42 亿级别,在互联网应有中,很容易就达到这个量级。比如一些日志表、浏览记录表等,每天 1000w 的数据增量,420 天后就达到了 INT 上限。

因此,用自增型做主键,应该使用 BIGINT,而不是 INT

另外,MySQL8.0 以前的版本,自增不持久化,自增值可能会存在回溯问题

我们以以下实例来看:

mysql> SELECT * FROM t;+---+| a |+---+| 1 || 2 || 3 |+---+3 rows in set (0.01 sec)mysql> DELETE FROM t WHERE a = 3;Query OK, 1 row affected (0.02 sec)mysql> SHOW CREATE TABLE t\G*************************** 1. row ***************************Table: tCreate Table: CREATE TABLE `t` (`a` int NOT NULL AUTO_INCREMENT,PRIMARY KEY (`a`)) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci1 row in set (0.00 sec

从上述代码可以看出,在删除自增为 3 的记录后,下一个自增依然为 4,这里没有问题,自增不会回溯。但如果此时数据库发生重启,那数据库启动后,表 t 的自增起始值会再次变为 3,这就是自增值发生回溯。

mysql> SHOW CREATE TABLE t\G*************************** 1. row ***************************Table: tCreate Table: CREATE TABLE `t` (`a` int NOT NULL AUTO_INCREMENT,PRIMARY KEY (`a`)) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci1 row in set (0.00 s

如果想解决这个问题,有以下两个做法:

  • 1、升级 MySQL 到 8.0 版本,让每个表的自增值持久化。

  • 2、如无法升级版本,则不推荐在核心业务表使用自增数据类型做主键。

其实在海量的互联网架构设计中,为了后续分布式架构更好的扩展,一般是不使用整型来做主键的,更为推荐的是使用字符串类型

2、资金字段设计

在用户余额、基金账户余额、数字钱包、零钱等的业务设计中,由于字段都是资金字段,通常技术人员习惯使用 DECIMAL 类型作为字段的选型,因为这样可以精确到分,如:DECIMAL(6,2)。

CREATE TABLE User (userId BIGINT AUTO_INCREMENT,money DECIMAL(8,2) NOT NULL,......)

在海量互联网业务的设计标准中,并不推荐用 DECIMAL 类型,而是更推荐将 DECIMAL 转化为 整型类型。也就是说,资金类型更推荐使用用分单位存储,而不是用元单位存储。如 1 元在数据库中用整型类型 100 存储。

金额字段的取值范围如果用 DECIMAL 表示的,如何定义长度呢?因为类型 DECIMAL 是个变长字段,若要定义金额字段,则定义为 DECIMAL(8,2) 是远远不够的。这样只能表示存储最大值为 999999.99,百万级的资金存储。

用户的金额至少要存储百亿的字段,而统计局的 GDP 金额字段则可能达到百万亿级别。用类型 DECIMAL 定义,不好统一。

另外重要的是,类型 DECIMAL 是通过二进制实现的一种编码方式,计算效率远不如整型来的高效。因此,推荐使用 BIG INT 来存储金额相关的字段

字段存储时采用分存储,即便这样 BIG INT 也能存储千兆级别的金额。这里,1 兆 = 1 万亿。

文章将持续更新,欢迎关注公众号:服务端技术精选。欢迎点赞、关注、转发

这篇关于MySQL数据库中的浮点类型和高精度类型有什么区别?为什么不推荐使用浮点类型?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/978112

相关文章

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

SQL中的外键约束

外键约束用于表示两张表中的指标连接关系。外键约束的作用主要有以下三点: 1.确保子表中的某个字段(外键)只能引用父表中的有效记录2.主表中的列被删除时,子表中的关联列也会被删除3.主表中的列更新时,子表中的关联元素也会被更新 子表中的元素指向主表 以下是一个外键约束的实例展示

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

如何去写一手好SQL

MySQL性能 最大数据量 抛开数据量和并发数,谈性能都是耍流氓。MySQL没有限制单表最大记录数,它取决于操作系统对文件大小的限制。 《阿里巴巴Java开发手册》提出单表行数超过500万行或者单表容量超过2GB,才推荐分库分表。性能由综合因素决定,抛开业务复杂度,影响程度依次是硬件配置、MySQL配置、数据表设计、索引优化。500万这个值仅供参考,并非铁律。 博主曾经操作过超过4亿行数据

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

Hadoop数据压缩使用介绍

一、压缩原则 (1)运算密集型的Job,少用压缩 (2)IO密集型的Job,多用压缩 二、压缩算法比较 三、压缩位置选择 四、压缩参数配置 1)为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器 2)要在Hadoop中启用压缩,可以配置如下参数

Makefile简明使用教程

文章目录 规则makefile文件的基本语法:加在命令前的特殊符号:.PHONY伪目标: Makefilev1 直观写法v2 加上中间过程v3 伪目标v4 变量 make 选项-f-n-C Make 是一种流行的构建工具,常用于将源代码转换成可执行文件或者其他形式的输出文件(如库文件、文档等)。Make 可以自动化地执行编译、链接等一系列操作。 规则 makefile文件

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置