当前位置:网站首页>mysql数据库设计
mysql数据库设计
2022-06-22 17:50:00 【xcrj】
理论
E-R (entity-relationship):实体、属性、关联(1:1, 1:n, m:n)
CDM (Conceptual Data Model):概念数据模型
PDM (Physical Data Model):物理数据模型
1NF范式:
- 字段原子性,实体属性不可再分
2NF范式:
- 部分依赖,通过候选键可以直接区分每个非候选键
- 在1NF范式的基础上消除非主属性对主码的部分依赖
3NF范式:
- 传递依赖,任何非主属性不依赖于其它非主属性
- 在2NF基础上消除-传递依赖
总结
要不要用数据库,用什么数据库,怎么用数据库
单体,分布式,数据类型,数据量,并发量,效率,安全
数据库只是数据的一种存储方式,也有一定的使用成本;某些情况下可以换一种数据存储方式,比如 JSON文件、Excel表格甚至txt文件
json存储和proto存储可以跨语言,json存储数据库类型是文本,proto格式存储是二进制
符合范式,加冗余(提高数据处理速度)
加索引
加视图(提高速度,表拆分后union视图)
安全:主从复制、mysql集群
效率:读写分离、分库分表、mysql集群
注意
不用mysql关键字做字段名,表名称
不使用外键,使用代码保证表与表之间的一致性
数据库
数据库:存储引擎、编码、排序规则
存储引擎:MyISAM与InnoDB
| 名称 | 锁定 | 事务 | 索引 |
|---|---|---|---|
| InnoDB | 行锁定 | 支持 | 没有限制 |
| MyISAM | 表锁定 | 不支持 | 最多64个索引, 索引中字段字节总和不得大于 1000 bytes |
| Merge | 前提:MYISAM引擎&&表结构一致,支持单表唯一索引 |
编码:
- utf-8mb4 (most bytes 4bytes):英文使用1个字节,中文使用3个字节来编码;特殊字符表情,宽字符4字节;可以存储表情符号
- utf-8:英文及符号占1个字节,中文及符号占3个字节,数字一个字节
- unicode:中文、英文都是2个字节
- utf-16:一般英文和中文都要占用2个字节;unicode扩展区汉字占用4个字节
- utf-32:所有字符4个字节
排序规则:
| 排序规则 | 优点 | 缺点 | 其他 |
|---|---|---|---|
| utf8_general_ci | 效率较高 | 正确性差 | 能接受ß = s(单s)而不是ss(双ss)则使用;ß = s |
| utf8_unicode_ci | 效率较低 | 正确性较高 | 德语和法语,utf8_unicode_ci工作的很好;ß = ss |
表
什么数据可以放到表里面
分类:基础表、扩展表、关联表
名称
参考网址
单表数据量大小控制在500万行以内
- 500万行不是mysql数据库的限制,修改表结构,备份,恢复限制
- 历史数据归档,解决日志数据过大
- 分库分表,解决表过大
谨慎使用mysql分区表,谨慎选择分区键??
- 逻辑上表现为一个表,物理上表现为多个文件
- 建议采用物理分表的方式管理大数据
禁止在mysql数据库中存储大的二进制文件
- 大文件往往需要随机IO操作太耗费时间
- mysql中存储地址URL即可
- 图片、文件存储于专用文件服务器
禁止在线上做数据库压力测试
关系
- 一对一:任意一方放入另一方的主键
- 一对多:在多的这一方放入一的这一方的主键
- 多对多:单独建表需要建立关联表
表/名称
前缀用于区分系统表和业务表
后缀代表表的分类
字段
字段
- 分类:通用字段、业务字段
- 字段类型和大小、默认为空和索引
- 字段名称,类型,长度、宽度、有无符号,默认值,允许为空,索引
- 主键、外键
- 冗余字段
设计
- 通用字段、业务字段分开
- 使用程序代替外键
- 空间合适:
- 类型精确,多用int、char;
- 长度精确,固定长度;
- 有无符号 unsigned
- 避免使用 text,blob
- 字段类型越大,建立索引占用空间越多,一页框能存储的索引节点就越少,遍历时磁盘IO就越多
- 磁盘中的索引节点会载入内存中的页框
- 尽可能把所有列定义为not null
- 聚集索引的生成要求唯一且非空
字段/数据类型
参考网址
数据类型
| 类型名 | 存储大小 | 字节数 | 介绍 |
|---|---|---|---|
| bit | 存储bit值,0或1,长度最大64位 | ||
| char | 宽度:0~85 | 0-255 bytes | 定长字符,显示变长,空间占用定长;255/3=85个汉字 |
| varchar | 宽度:0~5000~2万 | 0-65535 bytes | 变长字符,显示变长,空间占用变长;65535/3=21845个汉字;阿里显示宽度最大5000 |
| binary | 包含0或1字符 | ||
| varbinary | 包含0或1字符 | ||
| bigint | 8字节 | 无符号值:0 到约 10 的 19 次方 | 常用作主键 |
| tinyint | 1字节 | 无符号值:0 到 255 | 常用作字典类型 |
| int | 4字节 | 无符号值:0 到约 43 亿 | |
| smallint | 2字节 | 无符号值:0 到 65535 | |
| mediumint | 3字节 | 无符号:0到16777215(1千600万) | |
| double | 8bytes | (2.22…E-308,1.79… E+308) | 双精度,浮点数 |
| decimal(a,b) | 16bytes | a最大38,b在0~a之间 | decimal(10, 7):总长为10,小数长7 |
| float | 4bytes | (1.17…E-38,3.40…E+38) | 单精度,浮点数 |
| tinytext | 255bytes | 0-65 535 bytes | 255/3=85个汉字 |
| text | 65535/1024=64K | 0-65535 bytes | 65535/3=21845个汉字,约2万汉字 |
| mediumtext | 16777215/1024/1024=16M | 0-16 777 215 bytes | 16777215/3=5592405个汉字,559万汉字 |
| longtext | 4294967295/1024/1024/1024=4G | 0-4 294 967 295 bytes | 4294967295/3=1431655765个汉字,14亿汉字 |
| TINYBLOB | 255bytes | 0-255 bytes | 不超过 255 个字符的二进制字符串 |
| BLOB | 63.9KB | 0-65 535 bytes | 二进制形式的长文本数据 |
| MEDIUMBLOB | 15.9MB | 0-16 777 215 bytes | 二进制形式的中等长度文本数据 |
| LONGBLOB | 3.9GB | 0-4 294 967 295 bytes | 二进制形式的极大文本数据 |
注意:
- mysql varchar(3) 中的数字描述的是字符个数不是字节数:,不论中文 英文 数字 都是3个。
- 4.0版本以下,varchar(100),指的是100字节,如果存放UTF8汉字时,只能存33个(每个汉字3字节)
- 5.0版本以上,varchar(100),指的是100字符,无论存放的是数字、字母还是UTF8汉字(每个汉字3字节),都可以存放100个。
- BINARY 和 VARBINARY 类似于 CHAR 和 VARCHAR,前两个包含二进制字符串即包含字节字符串而不是字符字符串
- 整数类型只要设置了类型,存储大小由类型决定不由显示宽度决定
- navicat中整数类型后面括号中的数字,表示的是显示宽度,不表示存储长度,这点与 varchar、char 后面的数字含义是不同的。
- 经纬度:decimal(10, 7)只需要精确到小数点后 7 位,精度就是 1CM,因此,数据库保存经纬度采用 decimal(10, 7) 即可。
- 钱:decimal(15, 2)万亿.角分;或者直接到分的整数,
- 可以把小数和整数分开存储
- varchar:显示宽度最大5000
- bigint(20)自增做主键
- tinyint(0~255)做字典
- text:2万汉字
日期时间:
| 类型名 | 范围 | 格式 | 介绍 | 字节 |
|---|---|---|---|---|
| datetime | 1000-01-01 00:00:00/9999-12-31 23:59:59 | YYYY-MM-DD HH:MM:SS | 阿里规范datatime;是否需要根据当前时间更新;为null存储为null | 8字节 |
| timestamp | 1970-01-01 00:00:00/2038 | YYYYMMDD HHMMSS | 时间戳;timestamp会将时区存储进去;为null时为当前时间 | 4字节 |
| time | ‘-838:59:59’/‘838:59:59’ | HH:MM:SS | ||
| year | 1901/2155 | YYYY | ||
| date | 1000-01-01/9999-12-31 | YYYY-MM-DD |
注意:
- 时间默认值:CURRENT_TIMESTAMP
- create_time使用datetime,只在创建时使用
- update_time使用datetime,更新时需要更新这个字段
字段/公共字段
部分
id(bigint(20),主键,自增,无符号)
create_time(datetime) :创建时使用1次
update_time(datetime) :根据当前时间更新,默认值CURRENT_TIMESTAMP
tenant_id(bigint(20),无符号):租户ID
全部
id(bigint(20),主键,自增,无符号)
create_time(datetime) :创建时使用1次
update_time(datetime) :根据当前时间更新,默认值CURRENT_TIMESTAMP
delete_time(datetime):删除时使用1次
create_by(char(30)):创建者
update_by(char(30)):更新者
delete_by(char(30)):删除者
tenant_id(bigint(20),无符号):租户ID
data_scope:同一租户下,数据的范围
is_enabled(tiny_int(1),无符号):注释:是否启用 1:true启用 0:flase停用 默认:1
is_deleted(tiny_int(1),无符号):注释:是否删除 1:true删除 0:false未删除 默认:0
字段/默认值
避免字段默认值带来业务意义
直接用字段默认值设置为常用值
字段/名称
主键
环境分类:单体、分布式
生成算法:UUID、雪花算法
生成方法:mysql自增、java代码生成、ORM框架生成
innoDB数据库引擎时,使用int自增做主键
| 分类 | 说明 |
|---|---|
| mysql自增主键 | innoDB |
| mysql自带uuid | |
| ORM框架自动插入雪花算法 | |
| java生成uuid、雪花算法 |
- 设计经验:
- 使用自增主键;不方便获取数据库生成的id,框架会返回插入的数据对象
- 雪花算法:bigint(20)
- uuid:varchar(36)
外键
主表的主键作为从表的外键
删除时的约束:删除主表记录时,从表中的动作
- CASCADE(级联):删除主键表时,从表一并删除
- RESTRICT/NO ACTION:从表约束主表-主表中的记录在外键中有时,不可删除
- SET NULL:从表约束主表-主表中的记录在外键中有时,设置从表中该外键值为null
索引
- 索引建立,建立一个好的索引
- 联合索引左侧,放区分度高的(优先索引左侧),查询最频繁的,字段长度小的(1页能存储更多的索引节点)
- varchar字段建立索引,必须制定长度,长度=20时区分度=90%, count(distinct left(列名, 索引长度))/count(*)
- 索引使用,查询尽量使用到索引
- 建议单张表索引不超过5个
- 禁止给表中的每一列都建立单独的索引
- 每张表必须有主键
- 一般开发使用 普通索引和唯一索引就可以了
- 手机号设置唯一索引;身份证设置成唯一索引
- 与数据字典对应的表sys_dict 多建立索引
- 关联查询join字段建立索引
索引原理
- B+树
- 建立B+树的过程比较耗时
- 建立一颗好的B+树,有助于提高查询速度
索引名称:
- 主键索引:pk_ 字段名
- 唯一索引:uk_字段名
- 普通索引:idx_字段名
- 组合索引:idx_字段名1_字段名2
事务
分库分表
分库分表时机:523原则,单表行数超过 500 万行或者单表容量超过 2GB;预计三年后的数据量根本达不到这个级别,请不要在创建表时就分库分表。
分库:请求发布到不同的库处理,同一条请求单表的压力没有降低。
分表:数量合适
分表/水平拆分
方法1和方法3结合的方式来进行分表
- 预先估计会出现大数据量并且访问频繁的表,将其分为若干个表:映射方法 表id-(hash算法、取余算法)-分表表名
- 事先没有想到怎么办
- 换用算法就破坏了对应关系
- merge存储引擎:TYPE=MERGE UNION=(user1,user2) INSERT_METHOD=LAST
- 先有几张存储引擎为MYISAM的表+他们的表结构一致
- 一个 merge 表不能在整个表上维持 unique 索引,只能在单个表上维持unique索引。当你执行一个 insert,数据进入那张分表(取决于 insert_method 选项的值)
分表/垂直拆分
按业务拆分,把业务拆分的更加细
例子
传递依赖:employee表中有depart_code,depart_name;depart表中有depart_code,depart_name;如果depart表中的depart_name改变了,employee表中depart_name怎么办
对象数据库:mysql是结构化数据库,图片和文件等二进制文件实体放到对象数据库中,mysql中放入链接地址即可
主键:mybatis-plus雪花算法默认int类型19位,所以设计数据库时bigint(20)
字段:树形目录所需字段,id parent
例子/数据字典
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for sys_dict_type
-- ----------------------------
DROP TABLE IF EXISTS `sys_dict_type`;
CREATE TABLE `sys_dict_type` (
`dict_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '字典主键',
`dict_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '字典名称',
`dict_type` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '字典类型',
`status` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '状态(0正常 1停用)',
`create_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '创建者',
`create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '更新者',
`update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
`remark` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`dict_id`) USING BTREE,
UNIQUE INDEX `dict_type`(`dict_type`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 12 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '字典类型表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Table structure for sys_dict_data
-- ----------------------------
DROP TABLE IF EXISTS `sys_dict_data`;
CREATE TABLE `sys_dict_data` (
`dict_code` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '字典编码',
`dict_type` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '字典类型',
`dict_label` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '字典标签',
`dict_value` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '字典键值',
`is_default` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT 'N' COMMENT '是否默认(Y是 N否)',
`dict_sort` int(11) NULL DEFAULT 0 COMMENT '字典排序',
`status` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '状态(0正常 1停用)',
`create_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '创建者',
`create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '更新者',
`update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
`remark` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`dict_code`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 40 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '字典数据表' ROW_FORMAT = DYNAMIC;
SET FOREIGN_KEY_CHECKS = 1;
注意
- dict_type加上唯一前缀,区分不同业务的字典
参考文档
《阿里巴巴泰山版Java开发手册》
边栏推荐
- vs code突然无法进行代码跳转
- Exness sorted out three problems to be solved in Musk's acquisition of Twitter
- Complete the sqlsession interface and implementation classes
- How much do you know about the bloom filter and cuckoo filter in redis?
- Makefile将某一部分文件不编译
- 游戏NFT市场:OpenSea最易被切下的蛋糕
- 【工具】pip和conda的相關使用
- wpa_cli参数说明
- Which securities company is better to open an account when making an appointment to play new bonds? It is safer to open an account
- Chrome suddenly can't copy and paste
猜你喜欢

IPLOOK 5GC与亚信国际CHF(计费功能)对接成功

5G 短消息解决方案

新人报道的笔记

Zero basic programming / reverse learning / over detection (Frida practice)

Niuke.com: judge whether it is palindrome string

2022年R2移动式压力容器充装试题模拟考试平台操作

腾讯云国际版云服务器欠费说明

Unity中通过射线躲避障碍物寻路的一些初步探索

A course for New Oriental transformation bilingual live broadcast to bring goods to the project manager

In May, 2022, China's game manufacturers and applications went to sea, with top 30 revenue in EMEA region
随机推荐
UE4_UE5制作3DUI-跟随相机朝向(附工程)
A course for New Oriental transformation bilingual live broadcast to bring goods to the project manager
JVM快速入门
如何提高工作效率?苹果电脑效率工具合集
线程池:ThreadPoolExcutor源码阅读
基于云架构的业务稳定性建设思路
Some preliminary explorations of avoiding obstacles and finding paths by rays in unity
Jenkins installation and upgrade
牛客网:合并区间
自定义数据库连接池类: 要求:封闭一个Collection对象的集合类
Golang 實現 Redis(10): 本地原子性事務
Live streaming: dongyuhui is so popular. Is there anyone watching liuzhenhong?
Golang implements reliable delay queue based on redis
ADAU1452开发系统界面与代码数据之间的关系
Jenkins配置项目集成钉钉通知
每天5分钟玩转Kubernetes | Dashboard典型使用场景
Chrome suddenly can't copy and paste
JVM quick start
助力客户数字化转型,构建全新的运维体系
RSPS2022 Finalist | Dr. Yang Bai 简介