表的设计
前言:数据库设计在平时的工作是必不可少的,良好的表设计可以让我们查询效率更高,加快网站访问速度,提升用户体验,并且方便于我们查询数据。本篇博客就来聚焦一下,如何设计出高可复用,优良的表结构,从而在实际的工作中使我们写出更好的代码。
数据库表设计的几条黄金准则:
一:字段的原子性
解释:保证每列的原子性,不可分解,意思表达要清楚,不能含糊,高度概括字段的含义,能用一个字段表达清楚的绝不使用第二个字段,必须要使用两个字段表达清楚的绝不能使用一个字段
二:主键设计
解释:主键不要与业务逻辑有所关联,最好是毫无意义的一串独立不重复的数字,常见的比如UUID或者将主键设置为Auto_increment;
三:字段使用次数
解释:对于频繁修改的字段(一般是指状态类字段)最好用独立的数字或者单个字母去表示,不用使用汉字或长字符的英文
四:字段长度
解释:建表的时候,字段长度尽量要比实际业务的字段大3-5个字段左右(考虑到合理性和伸缩性),最好是2的n次方幂值。不能建比实际业务太大的字段长度(比如订单id如果考虑要业务增长的话,一定要使用Long型,对应的数据库的数据类型是bigint),这是因为如果字段长度过大,在进行查询的时候索引在B-Tree树上遍历会越耗费时间,从而查询的时间会越久;但是绝对不能建小,否则mysql数据会报错,程序会抛出异常;
五:关于外键
解释:尽量不要建立外键,保证每个表的独立性。如果非得保持一定的关系,最好是通过id进行关联
六:动静分离
解释:最好做好静态表和动态表的分离。这里解释一下静态表和动态表的含义,静态表:存储着一些固定不变的资源,比如城市/地区名/国家(静态表一定要使用缓存)。动态表:一些频繁修改的表
七:关于code值
解释:使用数字码或者字母去代替实际的名字,也就是尽量把name转换为code,因为name可能会变(万一变化就会查询处多条数据,从而抛出错误),但是code一般是不会变化的.另一方面,code值存储的字符较少,也能减少数据库的存储空间的压力
八:关于Null值
解释:尽量不要有null值,有null值的话,数据库在进行索引的时候查询的时间更久,从而浪费更多的时间!可以在建表的时候设置一个默认值!
九:关于引擎的选择
解释:关于引擎的选择,innodb与myisam,myisam的实际查询速度要比innodb快,因为它不扫面全表,但是myisam不支持事务,没办法保证数据的Acid。选择哪个这就要看自己对于效率和数据稳定性方面的实际业务的取舍了
十:资源存储
解释:数据库不要存储任何资源文件,比如照片/视频/网站等,可以用文件路径/外链用来代替,这样可以在程序中通过路径,链接等来进行索引
十一:与主键相关
解释:根据数据库设计三大范式,尽量保证列数据和主键直接相关而不是间接相关
十二:关系映射
解释:多对一或者一对多的关系,关联一张表最好通过id去建立关系,而不是去做重复数据,这样做最大的好处就是中间的关系表比较清楚明白。
十三:预留字段
解释:在设计一张表的时候应该预制一个空白字段,用于以后的扩展,因为你也不是确定这张表以后不会扩展。
十四:留下单一字段确定是否可用
解释:通过一个单一字段去控制表是否可用,比如通常起名为isVaild,预制的含义为0为有效,1为无效,这样便于以后我们去剔除数据或者重整数据,使其成为boolean性质的数据 更加便于我们去操控。
十五:删除字段
解释:数据库是禁止使用delete命令的,一般都不会真正删除数据,都是采用改状态的方式,设置state字段,通过修改状态赋予它是否有效的逻辑含义!
建表思路
1 表结构
2 字段类型 是否允许为null 是否有默认值
3 索引设计
4 数据库引擎的选择
在阐述两张表的多对多关系时 常会新建另一张表来存储两者的多对多关系---由很多一对一数据构成
一对多的关系常给‘多’的一方设置外键关联‘一’的主键
文章表还有‘是否审核通过’的字段
对一个字段的不同状态可以用 0 1 2 表示不同状态 而不是创建三个字段选其一
建表时的 int(3) int(6) 其中的数字只是代表显示字段的位数 不够用0 补齐 而不是代表实际使用长度 实际使用长度都由前面的数据类型指定了 是同样长的
电话号码一般用字符串格式储存 因为有的座机号码可能是0开头 如果用数字来存储 0开头的数据可能会丢失
char 与 varchar 的选择 :
char 不可变,查询效率高,可能造成存储浪费
varchar 可变,查询效率不如char,节省空间
主外键关系(索引设计)
-
CASCADE
在父表上update/delete记录时,同步update/delete掉子表的匹配记录
- ON DELETE:删除主表时自动删除从表。删除从表,主表不变
- ON UPDATE:更新主表时自动更新从表。更新从表,主表不变
SET NULL
在父表上update/delete记录时,将子表上匹配记录的列设为null (要注意子表的外键列不能为not null)
- ON DELETE:删除主表时自动更新从表值为NULL。删除从表,主表不变
- ON UPDATE:更新主表时自动更新从表值为NULL。更新从表,主表不变
NO ACTION
如果子表中有匹配的记录,则不允许对父表对应候选键进行update/delete操作
- ON DELETE:从表记录不存在时,主表才可以删除。删除从表,主表不变
- ON UPDATE:从表记录不存在时,主表才可以更新。更新从表,主表不变
RESTRICT
同no action, 都是立即检查外键约束
SET DEFAULT
父表有变更时,子表将外键列设置成一个默认的值 但Innodb目前不支持
-
索引 Key / Index
- 提升查询效率,减慢增删改速度
-
唯一约束 Unique
- 保证数据不重复
引擎
一个数据库中多个表可以使用不同引擎以满足各种性能和实际需求
SHOW ENGINES # 命令来查看MySQL提供的引擎 SHOW VARIABLES LIKE 'storage_engine'; # 查看数据库默认使用哪个引擎
1 InnoDB存储引擎(mysql默认引擎)
InnoDB给MySQL提供了具有提交、回滚和崩溃恢复能力的事物安全(ACID兼容)存储引擎
InnoDB支持外键完整性约束
2 MyISAM存储引擎
在Web、数据仓储和其他应用环境下最常使用的存储引擎之一。MyISAM拥有较高的插入、查询速度,但不支持事物,适合查询多 修改少的表
MyISAM类型表的AUTO_INCREMENT列更新比InnoDB类型的AUTO_INCREMENT更快
使用MyISAM引擎创建数据库,将产生3个文件。文件的名字以表名字开始,扩展名之处文件类型:frm文件存储表定义、数据文件的扩展名为.MYD(MYData)、索引文件的扩展名时.MYI(MYIndex
3 MEMORY存储引擎
储存在内存中 类似redis