mysql设计
大家好,我是捡田螺的小男孩。
昨天一位粉丝,咨询了一个并发的问题~ 我提供了一个乐观锁兜底的方案,然后发现他们的表,都没有加version字段的,我想到,这不是表设计通用字段嘛。因此,本文跟大家聊聊,设计表的时候,有哪些经验准则。
公众号:捡田螺的小男孩
- 设计表时,尽量都有这几个通用字段
表必备一般来说,或具备这几个字段:
id:主键,一个表必须得有主键,必须
create_time:创建时间,必须
modifed_time: 修改时间,必须,更新记录时,就更新它。
version : 数据记录的版本号,一般用于乐观锁,非必须
modifier :修改人,非必须
creator :创建人,非必须
图片
- 每个字段都要有注释,尤其涉及枚举这些时
我们在设计表的时候,每个字段,都要写上注释哈,尤其涉及到一个枚举字段的时候,更要把每个枚举值写出来,后面如果有变更,也要维护到这里来~
反例:
CREATE TABLE order_tab (
id INT AUTO_INCREMENT PRIMARY KEY,
order_id BIGINT UNIQUE,
user_id BIGINT NOT NULL,
total_amount DECIMAL(10, 2) NOT NULL,
status VARCHAR(20) NOT NULL DEFAULT ‘PENDING’,
payment_status VARCHAR(20) DEFAULT ‘not_paid’,
version INT DEFAULT 0,
created_time DATETIME,
updated_time DATETIME,
creator VARCHAR(255),
modifier VARCHAR(255)
);
正例:
CREATE TABLE order_tab (
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT ‘订单项的唯一标识符,自增主键’,
order_id BIGINT UNIQUE COMMENT ‘订单的唯一标识符,在整个系统中唯一’,
user_id BIGINT NOT NULL COMMENT ‘用户的唯一标识符,关联到用户表’,
total_amount DECIMAL(10, 2) NOT NULL COMMENT ‘订单的总金额,精确到小数点后两位’,
status VARCHAR(20) NOT NULL DEFAULT ‘PENDING’ COMMENT ‘订单的状态,例如:PENDING(待处理)、COMPLETED(已完成)等’,
payment_status VARCHAR(20) DEFAULT ‘not_paid’ COMMENT ‘订单的支付状态,如:not_paid(未支付)、paid(已支付)等’,
version INT DEFAULT 0 COMMENT ‘乐观锁版本号,用于并发控制’,
created_time DATETIME COMMENT ‘订单的创建时间’,
updated_time DATETIME COMMENT ‘订单的最后一次更新时间’,
creator VARCHAR(255) COMMENT ‘订单的创建者,通常记录创建订单的用户或系统的用户名’,
modifier VARCHAR(255) COMMENT ‘订单的修改者,通常记录最后修改订单的用户或系统的用户名’
);
3. 命名规范
数据库表名、字段名、索引名等都需要命名规范,可读性高(一般要求用英文),让别人一看命名,就知道这个字段表示什么意思。
比如一个表的账号字段,反例如下:
acc_no,1_acc_no,zhanghao
正例:
account_no,account_number
表名、字段名必须使用小写字母或者数字,禁止使用数字开头,禁止使用拼音,并且一般不使用英文缩写。
主键索引名为pk_字段名;唯一索引名为uk_字段名;普通索引名则为idx_字段名。
4. 选择合适的字段类型
设计表时,我们需要选择合适的字段类型,比如:
尽可能选择存储空间小的字段类型,就好像数字类型的,从tinyint、smallint、int、bigint从左往右开始选择
小数类型如金额,则选择 decimal,禁止使用 float 和 double。
如果存储的字符串长度几乎相等,使用 char 定长字符串类型。
varchar是可变长字符串,不预先分配存储空间,长度不要超过5000。
如果存储的值太大,建议字段类型修改为text,同时抽出单独一张表,用主键与之对应。
同一表中,所有varchar字段的长度加起来,不能大于65535. 如果有这样的需求,请使用TEXT/LONGTEXT 类型。
5. 主键设计要合理
主键设计的话,最好不要与业务逻辑有所关联。有些业务上的字段,比如身份证,虽然是唯一的,一些开发者喜欢用它来做主键,但是不是很建议哈。主键最 好是毫无意义的一串独立不重复的数字,比如UUID,又或者Auto_increment自增的主键,或者是雪花算法生成的主键等等;
图片
6.选择合适的字段长度
先问大家一个问题,大家知道数据库字段长度表示字符长度还是字节长度嘛?
其实在mysql中,varchar和char类型表示字符长度,而其他类型表示的长度都表示字节长度。比如char(10)表示字符长度是10, 而bigint(4)表示显示长度是4个字节,但是因为bigint实际长度是8个字节,所以bigint(4)的实际长度就是8个字节。
我们在设计表的时候,需要充分考虑一个字段的长度,比如一个用户名字段(它的长度5~20个字符),你觉得应该设置多长呢?可以考虑设置为 username varchar(32)。字段长度一般设置为2的幂哈(也就是2的n次方)。
- 优先考虑逻辑删除,而不是物理删除
什么是物理删除?什么是逻辑删除?
物理删除:把数据从硬盘中删除,可释放存储空间
逻辑删除:给数据添加一个字段,比如is_deleted,以标记该数据已经逻辑删除。
物理删除就是执行delete语句,如删除account_no =‘666’的账户信息SQL如下:
delete from account_info_tab whereaccount_no =‘666’;
逻辑删除呢,就是这样:
update account_info_tab set is_deleted = 1 where account_no =‘666’;
为什么推荐用逻辑删除,不推荐物理删除呢?
为什么不推荐使用物理删除,因为恢复数据很困难
物理删除会使自增主键不再连续
核心业务表 的数据不建议做物理删除,只适合做状态变更。
8. 一张表的字段不宜过多
我们建表的时候,要牢记,一张表的字段不宜过多哈,一般尽量不要超过20个字段哈。笔者记得上个公司,有伙伴设计开户表,加了五十多个字段。。。
如果一张表的字段过多,表中保存的数据可能就会很大,查询效率就会很低。因此,一张表不要设计太多字段哈,如果业务需求,实在需要很多字段,可以把一张大的表,拆成多张小的表,它们的主键相同即可。
当表的字段数非常多时,可以将表分成两张表,一张作为条件查询表,一张作为详细内容表 (主要是为了性能考虑)。
- 尽可能使用not null定义字段
如果没有特殊的理由, 一般都建议将字段定义为 NOT NULL 。
为什么呢?
首先, NOT NULL 可以防止出现空指针问题。
其次,NULL值存储也需要额外的空间的,它也会导致比较运算更为复杂,使优化器难以优化SQL。
NULL值有可能会导致索引失效
如果将字段默认设置成一个空字符串或常量值并没有什么不同,且都不会影响到应用逻辑, 那就可以将这个字段设置为NOT NULL。
10. 设计表时,评估哪些字段需要加索引
首先,评估你的表数据量。如果你的表数据量只有一百几十行,就没有必要加索引。否则设计表的时候,如果有查询条件的字段,一般就需要建立索引。但是索引也不能滥用:
索引也不要建得太多,一般单表索引个数不要超过5个。因为创建过多的索引,会降低写得速度。
区分度不高的字段,不能加索引,如性别等
索引创建完后,还是要注意避免索引失效的情况,如使用mysql的内置函数,会导致索引失效的
索引过多的话,可以通过联合索引的话方式来优化。然后的话,索引还有一些规则,如覆盖索引,最左匹配原则等等。。
假设你新建一张用户表,如下:
CREATE TABLE user_info_tab (
id int(11) NOT NULL AUTO_INCREMENT,
user_id int(11) NOT NULL,
age int(11) DEFAULT NULL,
name varchar(255) NOT NULL,
create_time datetime NOT NULL,
modifed_time datetime NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
对于这张表,很可能会有根据user_id或者name查询用户信息,并且,user_id是唯一的。因此,你是可以给user_id加上唯一索引,name加上普通索引。
CREATE TABLE user_info_tab (
id int(11) NOT NULL AUTO_INCREMENT,
user_id int(11) NOT NULL,
age int(11) DEFAULT NULL,
name varchar(255) NOT NULL,
create_time datetime NOT NULL,
modifed_time datetime NOT NULL,
PRIMARY KEY (id),
KEY idx_name (name) USING BTREE,
UNIQUE KEY un_user_id (user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
11. 避免使用MySQL保留字
如果库名、表名、字段名等属性含有保留字时,SQL语句必须用反引号来引用属性名称,这将使得SQL语句书写、SHELL脚本中变量的转义等变得非常复杂。
因此,我们一般避免使用MySQL保留字,如select、interval、desc等等
- 一般都选择INNODB存储引擎
建表是需要选择存储引擎的,我们一般都选择INNODB存储引擎,除非读写比率小于1%, 才考虑使用MyISAM 。
有些小伙伴可能会有疑惑,不是还有MEMORY等其他存储引擎吗?什么时候使用它呢?其实其他存储引擎一般除了都建议在DBA的指导下使用。
我们来复习一下这MySQL这三种存储引擎的对比区别吧:
图片
- 选择合适统一的字符集
数据库库、表、开发程序等都需要统一字符集,通常中英文环境用utf8。
MySQL支持的字符集有utf8、utf8mb4、GBK、latin1等。
utf8:支持中英文混合场景,国际通过,3个字节长度
utf8mb4: 完全兼容utf8,4个字节长度,一般存储emoji表情需要用到它。
GBK :支持中文,但是不支持国际通用字符集,2个字节长度
latin1:MySQL默认字符集,1个字节长度
14. 时间的类型选择
我们设计表的时候,一般都需要加通用时间的字段,如create_time、modified_time等等。那对于时间的类型,我们该如何选择呢?
对于MySQL来说,主要有date、datetime、time、timestamp 和 year。
date :表示的日期值, 格式yyyy-mm-dd,范围1000-01-01 到 9999-12-31,3字节
time :表示的时间值,格式 hh:mm:ss,范围-838:59:59 到 838:59:59,3字节
datetime:表示的日期时间值,格式yyyy-mm-dd hh:mm:ss,范围1000-01-01 00:00:00到9999-12-31 23:59:59```,8字节,跟时区无关
timestamp:表示的时间戳值,格式为yyyymmddhhmmss,范围1970-01-01 00:00:01到2038-01-19 03:14:07,4字节,跟时区有关
year:年份值,格式为yyyy。范围1901到2155,1字节 推荐优先使用datetime类型来保存日期和时间,因为存储范围更大,且跟时区无关。
- 安全性考虑
数据加密:敏感信息,如用户密码,应进行加密存储。如果是手机号、邮箱这些,则建议脱敏
相关文章:
mysql设计
大家好,我是捡田螺的小男孩。 昨天一位粉丝,咨询了一个并发的问题~ 我提供了一个乐观锁兜底的方案,然后发现他们的表,都没有加version字段的,我想到,这不是表设计通用字段嘛。因此,本文跟大家聊聊…...
Android 斗鱼面经
Android 斗鱼面经 文章目录 Android 斗鱼面经一面二面 一面 先简单描述一下JVM JRE JDK的关系 :::info JVM(Java Virtual Machine) Java 虚拟机。它只认识 xxx.class 这种类型的文件,它能够将 class 文件中的字节码指令进行识别并调用操作…...
【机器学习】26. 聚类评估方法
聚类评估方法 1. Unsupervised Measure1.1. Method 1: measure cohesion and separationSilhouette coefficient Method 2:Correlation between two similarity matricesMethod 3:Visual Inspection of similarity matrix 2. Supervised measures3. 决定…...
linux 最多能创建多少个 TCP 连接?
linux 最大允许TCP连接数 约束一:服务器的端口范围约束二,服务器文件描述符限制约束三:系统线程约束四:系统内存总结 tcp连接四元组:源ip,源端口 <> 目标ip,目标端口 连续对同一个目标ip及…...
我为何要用wordpress搭建一个自己的独立博客
我在csdn有一个博客,这个博客是之前学习编程时建立的。 博客有哪些好处呢? 1,可以写自己的遇到的问题和如何解决的步骤 2,心得体会,经验,和踩坑 3,可以转载别人的好的技术知识 4,宝贵…...
Linux系统每日定时备份mysql数据
一、创建存储脚本的文件夹 创建文件夹,我的脚本放在/root/dbback/mysql mkdir ... cd /root/dbback/mysql 二、编写脚本 vi backup_mysql.sh 复制脚本内容 DB_USER"填写用户名" DB_PASSWORD"填写密码" DB_NAME"数据库名称" # …...
书生大模型第一关Linux基础知识
任务一:完成SSH连接与端口映射并运行hello_world.py 1.SSH及其端口映射 2.在VSCode中安装插件: 3.创建开发机 最后点击创建,然后可能需要等待一段较长的时间,大概需要5分钟左右,如果需要排队则更长时间 然后选择…...
机器学习之fetch_olivetti_faces人脸识别--基于Python实现
fetch_olivetti_faces 数据集下载 fetch_olivetti_faceshttps://github.com/jikechao/olivettifaces sklearn.datasets.fetch_olivetti_faces(*, data_homeNone, shuffleFalse, random_state0, download_if_missingTrue, return_X_yFalse, n_retries3, delay1.0)[source] L…...
【系统设计】深入理解HTTP缓存机制:从Read-Through缓存到HTTP缓存的交互流程
在现代Web开发中,缓存机制扮演着至关重要的角色。它不仅提升了用户体验,还极大地优化了资源的使用效率。在这篇博文中,我们将从“Read-Through”缓存的概念出发,深入探讨HTTP缓存的工作原理和交互流程,并详细描述max-a…...
FLINK单机版安装部署入门-1
文章目录 FLINK单机版安装部署高于1.9.3需要修改配置文件flink-conf.yaml(低于1.9.3可以跳过)linux启动集群windows下启动Flink实例运行(单机)还有一种方式是上传任务包运行examples\streamingjava: Compilation failed: internal java compiler error高版本启动脚本 FLINK单机…...
深度学习-学习率调整策略
在深度学习中,学习率调整策略(Learning Rate Scheduling)用于在训练过程中动态调整学习率,以实现更快的收敛和更好的模型性能。选择合适的学习率策略可以避免模型陷入局部最优、震荡不稳定等问题。下面介绍一些常见的学习率调整策…...
【学员提问bug】小程序在onUnload里面调接口,用来记录退出的时间, 但是接口调用还没成功, 页面就关闭了。如何让接口在onUnload关闭前调用成功?
这种问题比较通用,并不涉及到具体方法执行障碍,所以,解决起来也不麻烦。但是新手往往不知道如何做。 在小程序中,如果在 onUnload 中调用 API 记录页面退出时间,但因为页面关闭速度较快导致请求未完成,可以…...
【刷题13】链表专题
目录 一、两数相加二、两两交换链表的节点三、重排链表四、合并k个升序链表五、k个一组翻转链表 一、两数相加 题目: 思路: 注意整数是逆序存储的,结果要按照题目的要求用链表连接起来遍历l1的cur1,遍历l2的cur2,和…...
Python Turtle模块详解与使用教程
Python Turtle模块详解与使用教程 引言 Python是一种广泛使用的编程语言,其简洁易读的语法使得它成为初学者学习编程的理想选择。而Turtle模块则是Python标准库中一个非常有趣且实用的图形绘制工具,特别适合用于教育和学习编程的基础知识。通过Turtle模…...
【PTA】4-2 树的同构【数据结构】
给定两棵树 T1 和 T2。如果 T1 可以通过若干次左右孩子互换就变成 T2,则我们称两棵树是“同构”的。例如图1给出的两棵树就是同构的,因为我们把其中一棵树的结点A、B、G的左右孩子互换后,就得到另外一棵树。而图2就不是同构的。 图一…...
Node.js——fs模块-同步与异步
本文的分享到此结束,欢迎大家评论区一同讨论学习,下一篇继续分享Node.js的fs模块文件追加写入的学习。...
Java基于微信小程序的私家车位共享系统(附源码,文档)
博主介绍:✌stormjun、8年大厂程序员经历。全网粉丝15w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇&…...
vscode 创建 vue 项目时,配置文件为什么收缩到一起展示了?
一、前言 今天用 vue 官方脚手架创建工程,然后通过 vscode 打开项目发现,配置文件都被收缩在一起了。就像下面这样 这有点反直觉,他们应该是在同一层级下的,怎么会这样,有点好奇,但是打开资源管理查看&…...
PySpark任务提交
一般情况下,spark任务是用scala开发的,但是对于一些偏业务人员,或者是基于上手的来说python的API确实降低了开发前置条件的难度,首当其冲的就是能跳过Java和Scala需要的知识储备,但是在提交任务到集群的时候就很麻烦了…...
【果蔬购物商城管理与推荐系统】Python+Django网页界面+协同过滤推荐算法+管理系统网站
一、介绍 果蔬购物管理与推荐系统。本系统以Python作为主要开发语言,前端通过HTML、CSS、BootStrap等框架搭建界面,后端使用Django框架作为逻辑处理,通过Ajax实现前后端的数据通信。并基于用户对商品的评分信息,采用协同过滤推荐…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...
【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...
23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...
【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...
MODBUS TCP转CANopen 技术赋能高效协同作业
在现代工业自动化领域,MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步,这两种通讯协议也正在被逐步融合,形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...
【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...
【Java学习笔记】BigInteger 和 BigDecimal 类
BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点:传参类型必须是类对象 一、BigInteger 1. 作用:适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...
