介绍数据库设计,表结构设计、访问设计、物理存储设计。
数据库设计思路:
1.单机: 单机就是把做的系统部署到一台服务器上,所有的请求业务都由这台服务器处理。显然,当业务增长到一定程度时,服务器的硬件会无法满足业务需求。
2.集群: 在多个服务器上部署多个服务,每个服务就是一个节点,部署N个节点,处理业务的能力就提升N倍(大约)。这些结点的集合就叫做集群。(资源浪费)
3.分布式: 把一个完整的系统,按照业务功能,拆分成一个个独立的子系统,在分布式结构中,每个子系统就被称为“服务”。 通过RPC(远程过程调用)方式通信。
其次可以基于1,2,3 加入读写分离,主从同步(一主一从,一主多从)等策略
第三方中间件
nginx,ridis,mongodb......
其他设置:
语言,编码格式,访问权限,数据库引擎选择(InnoDB,MyISAM,MEMORY,CSV,BLACKHOLE,FEDERATED)等设置
(InnoDB: 这是MySQL的默认数据库引擎,是一种事务安全的引擎,支持外键约束、行级锁定和崩溃恢复能力。
MyISAM: 这是MySQL的传统数据库引擎,提供了较快的查询性能,但是不支持事务处理和外键约束。
MEMORY: 这是一种内存引擎,可以将数据存储在内存中,提供较快的查询性能,但是不支持事务处理和外键约束。)
总结
个人观点: 好的设计应该是分布式和集群的结合,先分布式再集群,具体实现就是业务拆分成很多子业务,然后针对每个子业务进行集群部署,这样每个子业务如果出现了问题,整个系统完全不会受到影响,
于此同时加入监控系统等策略 如出现宕机等错误及时发出通知。(仅代表个人观点,不接受反驳。。。)
优点:
系统之间耦合度大大降低,可以独立开发、独立部署、独立测试,系统与系统之间的边界非常明确,排错也变得相当容易,开发效率大大提升。
系统之间的耦合度降低,从而系统更易于扩展。我们可以针对性地扩展某些业务,就是对子系统集群。例如双十一时,订单子系统、支付子系统需要集群,账户管理子系统不需要集群。
服务的复用性更高。比如,当我们将用户系统作为单独的服务后,该公司所有的产品都可以使用该系统作为用户系统,无需重复开发。
创建、设计表:
sql:
CREATE TABLE user (
id INT(11) NOT NULL ,
name VARCHAR(100) NOT NULL,
age INT(11) NOT NULL,
PRIMARY KEY (id)
)
表结构设计
字段类型的选择:
不同的数据类型可以存储不同类型的数据,如数字、文本、日期等。在数据库设计中,选择合适的数据类型是非常重要的,因为它会影响到数据的存储和查询效率。
举例(常用):
数值: int,number,float,Double,Decimal,
时间: date,timestamp
字符: text,varchar,varchar2,nvarchar2,char,nchar
true/false: boolean 值是用1代表TRUE,0代表FALSE
说明:
int/number: 存储整数类型
float: 存储小数和实数
Double: 精度和存储范围上更为合适,但存在着近似值的问题
Decimal: 固定的精度,因此它可以保存任意长度的数字
date(精确到秒)
timestamp(精确到小数秒,还能够显示上午还是下午)
char: 用于存储固定长度的数据,CHAR字段上的索引效率级高
nchar: 长度是在1到4000之间, 当于 char Plas版本
varchar: 长度不固定的,比如说,你定义了varchar(20),当你插入abc,则在数据库中只占3个字节。 专门存储可变长度的数据类型,但相应的损失存储效率
varchar2: varchar2最大长度支持4000个字符,和varchar的区别不是很大,但是建议使用varchar2,varchar2用null代替varchar的空字符串。
nvarchar2: nvarchar2最大长度支持4000个字符或4000个字节,nvarchar2相较与varchar2对汉字拥有更好的兼容性
text: 存储可变长度的非Unicode数据,最大长度为 65535 (2^16-1) 个字符 。
boolean: 值是用1代表TRUE,0代表FALSE
概括成:
CHAR,NCHAR 定长,速度快,占空间大,需处理
VARCHAR,NVARCHAR,TEXT 不定长,空间小,速度慢,无需处理
NCHAR、NVARCHAR、NTEXT 处理Unicode码
其他数据类型(例如微软 数据存储):
blob:最多可以存放4GB存储二进制数据
clob:最多可以存放4GB存储字符串数据
bfile:大小与操作系统有关用来把非结构化的二进制数据存储在数据库以外的操作系统文件中
主键生成策略:
ID 在进行表结构设计时,数字类型是最为常见的类型 INT 有什么缺陷呢?数据量大了怎么办? 对于金额的保存应该如何呢?(注:-128 - 127)
1. 自增主键:在插入新行时,通过自动增加ID的方式来唯一标识每一行数据。在创建表时,可以设置该列为AUTO_INCREMENT,会自动为该列分配一个初始值,并在每次插入数据时,自动递增该值。
CREATE TABLE user (
id INT(11) NOT NULL AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
age INT(11) NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
优缺点:
优点:id连续,容易进行排序,性能较好
缺点:分库分表时比较复杂,需要获取上一张表的末尾id,精度问题,合并表可能会出现主键重复的情况
2. UUID主键:在插入新数据时,通过使用随机生成的UUID字符串来唯一标识每一行数据。可以通过UUID()函数来生成UUID值,并在创建表时将该列设置为CHAR(36)类型。
CREATE TABLE user (
id CHAR(36) NOT NULL,
name VARCHAR(100) NOT NULL,
age INT(11) NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
优缺点:
优点:id值全球唯一(相同的概率是很低很低的) (UUID的生成算法基于时间戳和随机数。使用当前时间戳作为UUID的一部分,以确保UUID的唯一性。它还使用随机数来增加UUID的随机性,以防止重复)
缺点:占地方,降低性能,没办法根据id进行排序
3. 组合主键:在某些情况下,多个列的组合可以唯一标识每一行数据。(就是多个主键联合,体现联合)
CREATE TABLE user (
id INT(11) UNSIGNED NOT NULL,
email VARCHAR(100) NOT NULL,
PRIMARY KEY (id,email)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
优缺点:
优点:索引可以极大的提高数据的查询速度,
缺点:会降低,插入,删除,更新表的速度。
4.Redis生成
可以利用Redis的单线模型的优势来生成全局唯一的ID,调用redis的incr自增方法来生成。 例如设置ID字典表
优缺点:
优点:效率高、单线程 确保唯一
缺点:再搭一套Ridis服务,ridis宕机之类的问题。。。。
项目中的使用:
用基于注解的hibernate主键生成策略 自定义主键生成策略,由@GenericGenerator实现。 / UUID.randomUUID().toString()
@TableId(type = IdType.AUTO) AUTO:自动增长
@TableId(type = IdType.ID_WORKER)ID_WORKER:MP自带策略 (生成19位值,数字类型使用这种策略,例如Long)
@TableId(type = IdType.ID_WORKER_STR)ID_WORKER_STR:MP自带策略 (生成19位值,字符串类型使用这种策略)
@TableId(type = IdType.INPUT) INPUT:设置id
@TableId(type = IdType.UUID) UUID:随机唯一值
@TableId(type = IdType.NONE) NONE:自动输入
.....
表与表之间的关系设计:
需要考虑那些因素:
1.首先需要创建一个主表,主表是整个项目的重点,围绕主表创建分支。
2.需要考虑业务逻辑,比如多对多,一对多,一对一等代码逻辑。考虑表之间关系,需不需要创建中间表。示例: https://blog.csdn.net/lz1170063911/article/details/80498429
3.补充表中牵扯到其他表的字段,创建分支表。比如类型,字典等。
4.检查每张表是否有对应关系表,是否设计合理(必要性、是否符合相应的业务场景,减少冗余)
5.设计表需要遵循命名规范,有26个英文,下划线组成
6.主键:是一个表的唯一标识、
其他:
7.数据库性能:需要考虑到数据库的性能问题,包括表的大小、索引的使用、查询语句的优化,高可用等。
8.扩展性:表结构应该具有一定的扩展性,例如预留字段、可扩展的关系等。
9.安全:表结构应该考虑到安全问题,例如合理设置权限、避免SQL注入等。
访问设计:
…
物理存储设计:
…