Home | 简体中文 | 繁体中文 | 杂文 | Github | 知乎专栏 | 51CTO学院 | CSDN程序员研修院 | OSChina 博客 | 腾讯云社区 | 阿里云栖社区 | Facebook | Linkedin | Youtube | 打赏(Donations) | About
知乎专栏多维度架构

第 4 章 数据库设计

Database Modeling Design / RDBMS / ORDBMS / OODBMS / HDMS

目录

4.1. 数据库设计于使用规范
4.1.1. 建表规范
4.1.2. 查询规范
4.2. 关系型数据库设计
4.2.1. 数据字典
4.2.2. 用户帐号表
4.2.3. 分类表设计
4.2.4. 文章表设计
4.2.5. 评论表
4.2.6. 记录点击率,阅读次数,及评分表
4.2.7. 产品属性表
4.2.8. 商品库存表
4.2.9. 国际化语言表
4.2.10. Workflow
4.2.11. 内容版本控制
4.2.12. logging 日志表的设计
4.2.13. uuid 替代传统序列 id
4.2.14. 动态配置表
4.2.15. 验证码
4.2.16. 手机归属地数据库表
4.2.17. 数据检查
4.2.18. 创建与修改时间
4.2.19. 在线用户表
4.2.20. HTML TO Text
4.2.21. SNS 数据库设计
4.2.22. TINYINT(1) 还是 ENUM( 'true' , 'false')
4.2.23. PostgreSQL 所特有数据库设计
4.2.24. Sharding
4.2.25. MySQL 大数据操作注意事项
4.3. 数据库与缓存
4.3.1. 什么是数据库缓存?
4.3.2. 为什么缓存数据呢?
4.3.3. 什么时候使用数据库缓存
4.3.4. 涉及缓存的地方有哪些
4.3.5. 谁来控制数据库缓存
4.3.6. 怎么控制数据库缓存
4.4. 数据库并行访问控制
4.4.1. 防止并行显示
4.5. 数据库安全
4.5.1. 数据库结构版本控制
4.5.2. 保护表
4.5.3. 保护表字段
4.5.4. 时间一致性
4.5.5. 为数据安全而分库
4.5.6. 内容版本控制,撰改留痕
4.5.7. 数据库审计表
4.5.8. 用户/角色认证
4.5.9. Token 认证
4.5.10. 数据加密
4.5.11. 开发加密插件开发
4.5.12. 数据区块链
4.5.13. 状态保护
4.5.14. 数据归档
4.6. 参考例子
4.6.1. CMS 数据库设计
4.6.2. 微信公众平台
4.6.3. 电子商务网站
4.6.4. 数据属性例子
4.7. NoSQL OOD(Object-Oriented Design)
4.7.1. MongoDB
4.7.2. Cassandra
4.8. Spring Data 最佳实践
4.8.1. MySQL
4.8.2. MongoDB

下面数据库设计实例中,大部分使用MySQL,PostgreSQL为例,少部分以Oracle为例。

4.1. 数据库设计于使用规范

4.1.1. 建表规范

4.1.1.1. 使用 UNSIGNED 无符号整形

没有特别需要,不要使用有符号整形,尤其是是 AUTO_INCREMENT。

INT[(M)] [UNSIGNED] [ZEROFILL] M 默认为11 普通大小的整数。带符号的范围是-2147483648到2147483647。无符号的范围是0到4294967295。

			
CREATE TABLE `test` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
		
TRUNCATE `test`.`test`;
ALTER TABLE `test` AUTO_INCREMENT = 2147483645;
			
			

下面演示插入失败的情况,重复执行下面SQL插入数据

			
INSERT INTO `test`.`test` (`name`) VALUES ('chen');			
			
			

直到提示错误 Error Code: 1062. Duplicate entry '2147483647' for key 'PRIMARY' 表示 id 已经到了最大值,无法再插入数据。

			
CREATE TABLE `test` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2147483647 DEFAULT CHARSET=utf8mb4
			
			

现在改为无符号整形,然后在执行插入SQL

			
ALTER TABLE `test`.`test` CHANGE COLUMN `id` `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT ;			
			
			

再次调整 AUTO_INCREMENT 值,然后运行插入数据的 SQL

			
ALTER TABLE `test` AUTO_INCREMENT = 4294967295;
			
			

Error Code: 1062. Duplicate entry '4294967295' for key 'PRIMARY',INT已经达到最大值,此时仍需要插入数据,就需要将字段的数据类型改为 BIGINT

			
ALTER TABLE `test`.`test` CHANGE COLUMN `id` `id` BIGINT UNSIGNED NOT NULL ;
			
			

BIGINT[(M)] [UNSIGNED] [ZEROFILL] M默认为 20 大整数。带符号的范围是-9223372036854775808到9223372036854775807。无符号的范围是0到18446744073709551615。

4.1.1.2. 使用 ENUM( 'true' , 'false') 替代 TINYINT(1)

ENUM 提高数据可读性,TINYINT 需要查数据字典。

			
			
			
			

4.1.1.3. 尽量不使用 utf8mb4

GB2312 占用两个字节,UTF-8 占用三个字节,utf8mb4 占用4个字节。如果是大系统不建议使用 utf8mb4,他会增加磁盘的开销。

建议这样使用,数据库默认是 utf8,表也是 utf8,在需要存储表情符号是使用 utf8mb4

			
CREATE SCHEMA `netkiller_schema` DEFAULT CHARACTER SET utf8 ;

CREATE TABLE `netkiller_table` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(45) DEFAULT NULL,
  `nickname` varchar(45) CHARACTER SET utf8mb4 DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `id_UNIQUE` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8			
			
			

上面表中 name 存储姓名没有只有文字所以使用 utf8, nickname 昵称字段允许使用各种符号,所以使用 utf8mb4。

			
CREATE TABLE `test`.`table_utf8` (
  `name` VARCHAR(10) CHARACTER SET 'utf8' COLLATE 'utf8_general_ci' NOT NULL);
  
CREATE TABLE `test`.`table_utf8mb4` (
  `name` VARCHAR(10) CHARACTER SET 'utf8mb4' COLLATE 'utf8mb4_general_ci' NOT NULL);
  	
			
			

4.1.2. 查询规范

4.1.2.1. count(*) 可以使用吗?

可以使用,目前的数据库对 count(*) 都有优化

4.1.2.2. join 规范

4.1.2.3. 禁止 CONCAT

			
SELECT count(DISTINCT user_id)
FROM user_cooperate coo
WHERE coo.state = 1	AND coo.create_time <= CONCAT('2022-09-11', ' 23:59:59')