当前位置: 首页 > news >正文

设计表时,如何选择正确的数据类型

前言

假设现在有一个需求,需要创建一张orders表来存储客户的订单信息。假设表结构如下:

CREATE TABLE orders (order_id INT AUTO_INCREMENT PRIMARY KEY, -- 订单ID,主键,自增customer_id INT NOT NULL,                -- 客户ID,假设已在其他表中定义order_date DATETIME NOT NULL,            -- 订单日期和时间total_amount DECIMAL(10, 2) NOT NULL,    -- 订单总金额,保留两位小数
);

这里需要设计一个status 字段,用来表示订单的当前状态。订单状态可以是以下几种:待支付、已支付、发货中、已完成、已取消。

这个status字段在业务逻辑中非常重要,因为它会频繁地用于查询,更新等,方便用户查看自己处于不同状态的订单。

此时我们应该好好设计该字段,在保证其满足基本业务需求的同时,性能和扩展性这些方面也要充分考虑,避免之后较大的维护成本以及性能开销。

回到这个字段的设计来说,现在我们就有几种不同的数据类型选择来存储这个status字段,而且也能够基本得满足业务要求,比如VARCHAR 类型,ENUM 类型,TINYINT 类型,具体设计如下:

  • VARCHAR

我们可以选择使用字符串类型VARCHAR来直接存储状态文本(如"待支付"、"已支付"等)。

  • ENUM

我们可以使用枚举类型ENUM(‘待支付’, ‘已支付’, ‘发货中’, ‘已完成’, ‘已取消’)来存储这些状态。

  • TINYINT

我们可以选择使用较小的整数类型TINYINT,并为每种状态分配一个数字代码(如1=待支付,2=已支付等)。

这种情况下,status 字段时应该使用VARCHARENUM 还是TINYINT 类型呢?

在平时开发设计时,我们总是不可避免说会遇到类似这种选择。这种情况下我们应该怎么抉择呢? 能从哪些方面考虑呢?

数据类型选择的原则

在 MySQL 数据表设计时,选择合适的数据类型对于提高 数据库 的性能是至关重要且基础的。下面介绍一些简单的原则,帮助我们在遇到选择时,能过做出更好的选择。

更小的更好


选择能够在满足需求的前提下,占用最小存储空间的数据类型。

在执行查询和其他操作时会将数据加载到内存中,使用较小的数据类型可以减少内存使用,从而允许更多的数据同时驻留在内存中,提高数据的处理速度。同时它们占用更少的磁盘、CPU缓存,并且处理时需要的CPU周期也更少。

同时,数据类型的大小也会对索引的性能产生影响。较小的数据类型也可以提高索引的效率,字段占据空间越小,该字段对应的索引更小,可以提高索引的查找速度并减少磁盘I/O操作。这对查询性能有显著影响,尤其是对于大量数据和高负载的系统来说。

举例来说,如果你知道一个字段的值不会超过 255,那么使用 TINYINT 而不是 INT,这个不管是在存储空间还是查询效率上来说,都是TINYINT的性能更好。

但是要确保没有低估需要存储的值的范围,因为扩展数据类型的范围是一个非常耗时和痛苦的操作,也降低了系统的可维护性和扩展性,这样子就得不偿失了。

优先使用内建类型


在数据库设计中,应该优先使用数据库的内置类型的表示,而不是一些通用类型。

优先使用数据库内建类型有以下好处:

性能方面,数据库都会对内建数据类型进行了优化,以提供更好的存储和检索性能。例如,内建的数值和日期类型通常比通用的字符串类型在索引、排序和比较操作中表现得更好。

数据完整性方面,内建数据类型通常包括数据验证功能,可以在数据插入或更新时自动进行类型检查。这有助于防止无效数据的输入,从而维护数据的一致性和准确性。举例来说,DATE类型的字段将自动拒绝任何不符合日期格式的数据。

具有更高的存储效率。因为它们是针对所存储数据的性质量身定做的。例如,整数类型(如 INT 或 BIGINT)通常比等效的字符串表示(如数字的文本形式)占用更少的存储空间。

简化查询。内建数据类型可以简化查询语句的编写,因为它们不需要额外的转换或格式化函数。例如,使用 DATE 类型可以直接比较日期,而不需要将字符串转换为日期。

因此,在数据库设计中,我们应该优先使用系统内建的数据类型,只有在内建字段不满足需求的情况下,才考虑一些通用数据类型来表示。

优先使用简单类型


简单和复杂数据类型的界定并没有一个严格的标准,这些术语更多地是相对的,并且取决于上下文。

这里的简单和复杂是相对于操作和处理这些数据类型所需的资源来说的。

当我们说简单类型时,我们通常是指这些类型在数据库中的处理更加直接和高效。而复杂类型则可能需要更多的处理步骤,更多的资源,或者更复杂的内部表示。

当我们在数据库设计时,某个字段类型有多种选择,那么其中需要更多的存储空间,查询排序等操作更为复杂,性能更为低下的,此时该字段类型在该场景下就被界定为复杂类型。

这里举个例子说明一下,假设我们在用户信息表中有一个字段用于存储性别。性别通常只有几个固定的选项,例如“男”、“女”、“未指定”等。

在这种情况下,可以使用整数来表示,约定一个小的整数来表示性别,比如,0:未指定,1:男,2:女。

也可以使用字符串类型 (VARCHAR) 来存储性别信息。这种方式在表达上更直观,但它比简单数据类型更复杂、更耗费资源。

在这个场景下,字符串类型 相对于 整数类型 来说,其需要占用更多的存储空间,查询排序时也需要耗费更多的cpu和内存资源,此时字符串类型将被定义为复杂类型,整数类型相对的就是简单类型了。

在设计数据库时,考虑使用简单数据类型而不是复杂数据类型可以在确保足够表达能力的同时,提高数据库操作的效率。

考虑数据精度


在数据库设计时,选择合适的数据精度是非常重要的。选择过高或过低的精度都会带来问题:过高的精度可能会导致不必要的存储空间浪费和性能下降,而过低的精度则可能导致数据失真,无法满足业务需求。

经常的一个常见误区是数据精度越大越好,但是业务场景并不需要那么精确,此时使用过高的精度意味着需要更多的存储空间,这在大型数据库中尤其成问题,可能导致额外的存储成本。更高的精度可能会导致计算速度变慢,尤其是在进行数学运算、排序和索引操作时。

此时应该是从业务需求出发,选择最为合适的数据精度,既满足了业务要求,也避免了存储空间的浪费和查询性能的下降。

考虑扩展性


数据库设计时,需要考虑到后续需求的变化,随着时间的推移,数据库设计应该能够很好得适应业务的增长和变化,而不需要进行昂贵的重构。

上面提到了数据类型应该越小越好,但是这个需要考虑后续的扩展性。比如,当选择数值类型时,如果预计记录数量会非常大,就应该选择 BIGINT 而不是 INT。对于字符串类型,此时应该分配一个足够容纳未来可能增长的内容长度的大小。

再比如字符串类型的选择,如果字符串长度在当前是不可预见的,此时使用 VARCHAR 类型 相对于 CHAR 类型就更为灵活,它可以存储可变长度的字符串,节省空间并且可以容纳未来长度的变化。

总之,当数据库设计时,要充分考虑到后续可能的变化,避免在数据库需要支持更多数据和更复杂查询时进行成本高昂的重构。

选择什么类型呢

回到文章开头的问题,我们就有几种不同的数据类型选择来存储这个status字段,如VARCHAR 类型,ENUM 类型,TINYINT 类型,此时我们应该使用哪个字段类型呢?

这里我们使用上面几个简单原则来帮助我们做出判断,从而帮助我们做出更好的选择。

数据类型/考虑因素VARCHARTINYINTENUM
占用空间由于状态字符串的长度可能不一致,VARCHAR 可能会使用更多存储空间。TINYINT需要非常少的存储空间(通常是1个字节)。ENUM类型相对于VARCHAR类型更节省空间,因为它内部使用数值来表示每个可能的值。
内建类型不涉及不涉及不涉及
简单类型字符串索引排序效率相对更慢查询性能高,存储效率高,相对 VARCHAR 为简单类型底层数据表示上实际上是使用整数索引来存储的。查询性能高,存储效率高,相对VARCHAR 为简单类型
数据精度不涉及不涉及不涉及
扩展性新增一个枚举简单,可扩展性强可容纳127个状态,满足未来可见的变化,可扩展性强可扩展性差,每新增一个枚举,都需要重建表

基于以上分析,可以看出来,相比于VARCHARENUM 类型,TINYINT 是一个合适的选择,其提供了最好的存储效率,数据处理性能,可扩展性也比较强,完全能够适应未来业务需求的变化。

基于此,status 字段类型最终 选择 TINYINT 字段类型。最终的表结构如下:

CREATE TABLE orders (   order_id INT AUTO_INCREMENT PRIMARY KEY, -- 订单ID,主键,自增customer_id INT NOT NULL,                -- 客户ID,假设已在其他表中定义order_date DATETIME NOT NULL,            -- 订单日期和时间total_amount DECIMAL(10, 2) NOT NULL,    -- 订单总金额,保留两位小数status TINYINT NOT NULL,                 -- 订单状态,使用TINYINT类型
);  

总结

MySQL 支持的数据类型非常多,在合适的场景下,选择正确的数据类型对于获得高性能至关重要。

本文讲述了几个简单的原则,如选择最小存储空间的数据类型,使用内建类型,优先使用简单类型等。

这几个原则的核心思想,都是尽量选择更为简单的数据类型,减少磁盘空间或者cpu资源的浪费,从而获得更好的性能。

通过这几个简单的原则,希望能够帮助你在数据库设计时做出更好的选择。

本文由mdnice多平台发布

相关文章:

设计表时,如何选择正确的数据类型

前言 假设现在有一个需求,需要创建一张orders表来存储客户的订单信息。假设表结构如下: CREATE TABLE orders (order_id INT AUTO_INCREMENT PRIMARY KEY, -- 订单ID,主键,自增customer_id INT NOT NULL, -- 客户ID&#xf…...

iZotope RX 7 Advanced:音频修复与编辑的巅峰之作

在音频处理领域,iZotope RX 7 Advanced无疑是一款强大的软件,它集合了众多先进的音频修复和编辑功能,为用户提供了全方位的音频处理解决方案。 首先,iZotope RX 7 Advanced具备强大的噪声削减功能。无论是环境噪音、背景杂音还是…...

Mac 制作可引导安装器

Mac 使用U盘或移动固态硬盘制作可引导安装器(以 Monterey 为例) 本教程参考 Apple 官网相关教程 创建可引导 Mac OS 安装器 重新安装 Mac OS 相关名词解释 磁盘分区会将其划分为多个单独的部分,称为分区。分区也称为容器,不同容器…...

深入了解 JavaScript 混淆加密和环境检测

JavaScript混淆加密是一种通过修改代码结构和命名约定来增加代码的复杂性,使其难以被理解和逆向工程的技术。在这篇文章中,我们将深入探讨JS混淆加密的一些逻辑,并介绍如何通过环境检测来提高代码的安全性。我们将使用案例代码演示这些概念。…...

可让照片人物“开口说话”阿里图生视频模型EMO,高启强普法

3 月 1 日消息,阿里巴巴研究团队近日发布了一款名为“EMO(Emote Portrait Alive)”的 AI 框架,该框架号称可以用于“对口型”,只需要输入人物照片及音频,模型就能够让照片中的人物开口说出相关音频&#xf…...

全国产飞腾E2000Q +复旦微FPGA的轨道交通、电力解决方案

产品概述 ITX-XMF201是一款高性能边缘计算网关主板,采用飞腾E2000Q 4核处理器,国产化率达到95%国产化。 板载2电口,2路CAN,6路RS232接口,1路RS485接口,16路GPIO,可以满足银行、轨道交通、电力等…...

292.【华为OD机试】跳马问题(广度优先搜索(BFS)JavaPythonC++JS实现)

🚀点击这里可直接跳转到本专栏,可查阅顶置最新的华为OD机试宝典~ 本专栏所有题目均包含优质解题思路,高质量解题代码(Java&Python&C++&JS分别实现),详细代码讲解,助你深入学习,深度掌握! 文章目录 一. 题目二.解题思路三.题解代码Python题解代码JAVA题解…...

Qt 中Qwidget相关属性

文章目录 1. QWidget 核心属性1.1 enabled1.2 geometry1.2.1 window frame 的影响 1.3 windowTitle1.4 windowIcon1.4.1 qrc的使用 1.5 windowOpacity1.6 cursor1.7 focusPolicy1.8 styleSheet 1. QWidget 核心属性 在 Qt 中, 使⽤ QWidget 类表⽰ “控件”. 像按钮, 视图, 输…...

matplotlib散点图

matplotlib散点图 假设通过爬虫你获取到了北京2016年3, 10月份每天白天的最高气温(分别位于列表a, b), 那么此时如何寻找出气温和随时间(天)变化的某种规律? from matplotlib import pyplot as pltx_3 range(1, 32) x_10 range(51, 82)y_3 [11,17,16,11,12,11,12,6,6,7,8…...

day32贪心算法 part02

贪心系列的时候,题目和题目之间貌似没有什么联系,是真的就是没什么联系,因为贪心无套路,没有个整体的贪心框架解决一系列问题,只能是接触各种类型的题目锻炼自己的贪心思维。贪心只是一类题的统称,并没有什么固定套路。 122. 买卖…...

判断docker 镜像启动成功 shell脚本

要编写一个Shell脚本来判断Docker镜像是否启动成功,你可以使用docker ps命令来检查容器是否在运行状态。以下是一个简单的Shell脚本示例,用于判断Docker镜像是否成功启动: #!/bin/bash# 指定要检查的容器名称或ID CONTAINER_NAME"your_c…...

Android AppCompatActivity 方法详解

在 Android 开发中,AppCompatActivity 是一个常用的类,它提供了对新版 Android 特性在旧版 Android 上的兼容支持。作为 Android 支持库的一部分,它通常被用作活动(Activity)的基类。下面我们将介绍 AppCompatActivity…...

[FastDDS] 基于eProsima FastDDS的移动机器人数据中间件——介绍与准备工作

[FastDDS] 基于eProsima FastDDS的移动机器人数据中间件——介绍与准备工作 注明:无 本栏目主要讲述,基于eProsima FastDDS的移动机器人数据中间件的实现、使用、性能测试。 What is [ FastDDS ]: eProsima Fast DDS是DDS(数据分发服务&…...

4. 编写app组件

1. 代码 main.ts // 引入createApp用于创建应用 import {createApp} from "vue"// 引入App根组件 import App from ./App.vue createApp(App).mount(#app) App.vue <!-- vue文件可以写三种标签1. template标签&#xff0c;写html结构2. script 脚本标签&…...

经典的算法面试题(1)

题目&#xff1a; 给定一个整数数组 nums&#xff0c;编写一个算法将所有的0移到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 示例: 输入: [0,1,0,3,12] 输出: [1,3,12,0,0] 注意&#xff1a;必须在原数组上操作&#xff0c;不能拷贝额外的数组。尽量减少操作次数。 这…...

微信小程序 --- mobx-miniprogram miniprogram-computed

1.1 mobx-miniprogram 介绍 目前已经学习了 6 种小程序页面、组件间的数据通信方案&#xff0c;分别是&#xff1a; 数据绑定&#xff1a;properties获取组件实例&#xff1a;this.selectComponent()事件绑定&#xff1a;this.triggerEvent()获取应用实例&#xff1a;getApp(…...

【HTML】HTML基础2(一些常用标签)

目录 例子 首先是网页图标 然后是一些常用标签 插入图片 例子 <!DOCTYPE html> <html><head><link rel"icon" href"img/银河护卫队-星爵.png" type"image/x-icon"><meta charset"utf-8"><title>…...

Jmeter 安装

JMeter是Java的框架&#xff0c;因此在安装Jmeter前需要先安装JDK&#xff0c;此处安装以Windows版为例 1. 安装jdk&#xff1a;Java Downloads | Oracle 安装完成后设置环境变量 将环境变量JAVA_HOME设置为 C:\Program Files\Java\jdk1.7.0_25 在系统变量Path中添加 C:\Pro…...

控制液压比例插装阀放大器

比例阀放大器接收来自控制器的低功率电信号&#xff0c;并将其转换为足以驱动比例阀的高功率信号。与传统的开关型电磁铁不同&#xff0c;比例电磁铁可以实现连续控制&#xff0c;允许阀门在开和关之间进行无级调节&#xff0c;从而实现更精细的流量和压力控制。一个完整的电液…...

[设计模式Java实现附plantuml源码~行为型]定义算法的框架——模板方法模式

前言&#xff1a; 为什么之前写过Golang 版的设计模式&#xff0c;还在重新写Java 版&#xff1f; 答&#xff1a;因为对于我而言&#xff0c;当然也希望对正在学习的大伙有帮助。Java作为一门纯面向对象的语言&#xff0c;更适合用于学习设计模式。 为什么类图要附上uml 因为很…...

Docker 离线安装指南

参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性&#xff0c;不同版本的Docker对内核版本有不同要求。例如&#xff0c;Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本&#xff0c;Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...

基于FPGA的PID算法学习———实现PID比例控制算法

基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容&#xff1a;参考网站&#xff1a; PID算法控制 PID即&#xff1a;Proportional&#xff08;比例&#xff09;、Integral&#xff08;积分&…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件

在选煤厂、化工厂、钢铁厂等过程生产型企业&#xff0c;其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进&#xff0c;需提前预防假检、错检、漏检&#xff0c;推动智慧生产运维系统数据的流动和现场赋能应用。同时&#xff0c;…...

PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建

制造业采购供应链管理是企业运营的核心环节&#xff0c;供应链协同管理在供应链上下游企业之间建立紧密的合作关系&#xff0c;通过信息共享、资源整合、业务协同等方式&#xff0c;实现供应链的全面管理和优化&#xff0c;提高供应链的效率和透明度&#xff0c;降低供应链的成…...

Android15默认授权浮窗权限

我们经常有那种需求&#xff0c;客户需要定制的apk集成在ROM中&#xff0c;并且默认授予其【显示在其他应用的上层】权限&#xff0c;也就是我们常说的浮窗权限&#xff0c;那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...

深度学习习题2

1.如果增加神经网络的宽度&#xff0c;精确度会增加到一个特定阈值后&#xff0c;便开始降低。造成这一现象的可能原因是什么&#xff1f; A、即使增加卷积核的数量&#xff0c;只有少部分的核会被用作预测 B、当卷积核数量增加时&#xff0c;神经网络的预测能力会降低 C、当卷…...

NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合

在汽车智能化的汹涌浪潮中&#xff0c;车辆不再仅仅是传统的交通工具&#xff0c;而是逐步演变为高度智能的移动终端。这一转变的核心支撑&#xff0c;来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒&#xff08;T-Box&#xff09;方案&#xff1a;NXP S32K146 与…...

音视频——I2S 协议详解

I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议&#xff0c;专门用于在数字音频设备之间传输数字音频数据。它由飞利浦&#xff08;Philips&#xff09;公司开发&#xff0c;以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...

20个超级好用的 CSS 动画库

分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码&#xff0c;而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库&#xff0c;可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画&#xff0c;可以包含在你的网页或应用项目中。 3.An…...

FFmpeg:Windows系统小白安装及其使用

一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】&#xff0c;注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录&#xff08;即exe所在文件夹&#xff09;加入系统变量…...