数据库库表常见设计笔记

突然想整理下以前项目中遇到的数据库库表设计的简单思路,下面以网上商品的表设计为例:
商品有分类、品牌,如果按照简单思路来看创建三张表good、brand、category就可以了,但是在真正项目中往往不是那么简单。

根据表关系设计库表
1、树形结构:树形结构表一般用id和parent_id来设计
这里商品分类表(tb_category)分了3个层级,当然也可以为4个,这里不论

--商品分类表(tb_category)
CREATE TABLE `tb_category` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '类目id',
  `name` varchar(20) NOT NULL COMMENT '类目名称',
  `parent_id` bigint(20) NOT NULL COMMENT '父类目id,顶级类目填0',
  `is_parent` tinyint(1) NOT NULL COMMENT '是否为父节点,0为否,1为是',
  `sort` int(4) NOT NULL COMMENT '排序指数,越小越靠前',
  PRIMARY KEY (`id`),
  KEY `key_parent_id` (`parent_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1424 DEFAULT CHARSET=utf8 COMMENT='商品类目表,类目和商品(spu)是一对多关系,类目与品牌是多对多关系';

2、多对一:用关系为“一”的表的主键作为本表中的一个字段
一个商品分类下面有多种商品,所以商品spu表(tb_spu)、商品属性表(tb_spec)和商品分类表(tb_category)是“多对一”的关系。

--商品的属性表(tb_spec)
CREATE TABLE `tb_spec` (
   id bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'spec id',
  `category_id` bigint(20) NOT NULL COMMENT '商品三级类目id',
  `specifications` varchar(3000) NOT NULL DEFAULT '' COMMENT '规格参数模板,json格式',
  PRIMARY KEY (`category_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='商品规格参数模板,json格式。';


--商品spu表(tb_spu)
CREATE TABLE `tb_spu` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'spu id',
  `title` varchar(255) NOT NULL DEFAULT '' COMMENT '标题',
  `sub_title` varchar(255) DEFAULT '' COMMENT '子标题',
  `cid1` bigint(20) NOT NULL COMMENT '1级类目id',
  `cid2` bigint(20) NOT NULL COMMENT '2级类目id',
  `cid3` bigint(20) NOT NULL COMMENT '3级类目id',
  `brand_id` bigint(20) NOT NULL COMMENT '商品所属品牌id',
  `saleable` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否上架,0下架,1上架',
  `valid` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否有效,0已删除,1有效',
  `create_time` datetime DEFAULT NULL COMMENT '添加时间',
  `last_update_time` datetime DEFAULT NULL COMMENT '最后修改时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=216 DEFAULT CHARSET=utf8 COMMENT='spu表,该表描述的是一个抽象性的商品,比如 iphone8';

spu和sku的含义可以去百度查询,商品sku表(tb_sku)和商品spu表(tb_spu)也是“多对一”的关系。

--商品sku表(tb_sku)
CREATE TABLE `tb_sku` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'sku id',
  `spu_id` bigint(20) NOT NULL COMMENT 'spu id',
  `title` varchar(255) NOT NULL COMMENT '商品标题',
  `images` varchar(1000) DEFAULT '' COMMENT '商品的图片,多个图片以‘,’分割',
  `price` bigint(15) NOT NULL DEFAULT '0' COMMENT '销售价格,单位为分',
  `indexes` varchar(100) DEFAULT '' COMMENT '特有规格属性在spu属性模板中的对应下标组合',
  `own_spec` varchar(1000) DEFAULT '' COMMENT 'sku的特有规格参数键值对,json格式,反序列化时请使用linkedHashMap,保证有序',
  `enable` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否有效,0无效,1有效',
  `create_time` datetime NOT NULL COMMENT '添加时间',
  `last_update_time` datetime NOT NULL COMMENT '最后修改时间',
  PRIMARY KEY (`id`),
  KEY `key_spu_id` (`spu_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=27359021555 DEFAULT CHARSET=utf8 COMMENT='sku表,该表表示具体的商品实体,如黑色的 64g的iphone 8';

3、多对多:设计一张中间表,把两张关系为“多”的表的主键作为中间表中的两个字段
一个品牌(厂商)下可以有多个商品分类,一个分类下也可以有多个品牌,所以商品品牌表(tb_brand)和商品分类表(tb_category)是“多对多”的关系。

--商品品牌表(tb_brand)
CREATE TABLE `tb_brand` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '品牌id',
  `name` varchar(50) NOT NULL COMMENT '品牌名称',
  `image` varchar(200) DEFAULT '' COMMENT '品牌图片地址',
  `letter` char(1) DEFAULT '' COMMENT '品牌的首字母',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=325402 DEFAULT CHARSET=utf8 COMMENT='品牌表,一个品牌下有多个商品(spu),一对多关系';

--商品分类-品牌关系表(tb_category_brand)
CREATE TABLE `tb_category_brand` (
  `category_id` bigint(20) NOT NULL COMMENT '商品类目id',
  `brand_id` bigint(20) NOT NULL COMMENT '品牌id',
  PRIMARY KEY (`category_id`,`brand_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='商品分类和品牌的中间表,两者是多对多关系';

4、分表
垂直拆分:用另一张表的主键作为本表的主键
1)把表中存储大字段数据的字段分出来

--商品spu中的一些大字段信息
CREATE TABLE `tb_spu_detail` (
  `spu_id` bigint(20) NOT NULL,
  `description` text COMMENT '商品描述信息',
  `specifications` varchar(3000) NOT NULL DEFAULT '' COMMENT '全部规格参数数据',
  `spec_template` varchar(1000) NOT NULL COMMENT '特有规格参数及可选值信息,json格式',
  `packing_list` varchar(1000) DEFAULT '' COMMENT '包装清单',
  `after_service` varchar(1000) DEFAULT '' COMMENT '售后服务',
  PRIMARY KEY (`spu_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

2)把操作频繁的表字段分出来

--商品sku的库存和秒杀(tb_stock)
CREATE TABLE `tb_stock` (
  `sku_id` bigint(20) NOT NULL COMMENT '库存对应的商品sku id',
  `seckill_stock` int(9) DEFAULT '0' COMMENT '可秒杀库存',
  `seckill_total` int(9) DEFAULT '0' COMMENT '秒杀总数量',
  `stock` int(9) NOT NULL COMMENT '库存数量',
  PRIMARY KEY (`sku_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='库存表,代表库存,秒杀库存等信息';

水平拆分
针对数据量大的表还可以做水平拆分,水平拆分后的表主键可以用以下方法生成:
1、用redis的自增长序列生成
2、部署一台专门生成id的服务
3、用一些开源算法:如twitter的snowflake

雪花算法会生成一个64位的二进制数据,为一个Long型。(转换成字符串后长度最多19位) ,其基本结构:
在这里插入图片描述

  • 第一位:未使用
  • 第二部分:41位为毫秒级时间(41位的长度可以使用69年)
  • 第三部分:5位datacenterId和5位workerId(10位的长度最多支持部署1024个节点)
  • 第四部分:最后12位是毫秒内的计数(12位的计数顺序号支持每个节点每毫秒产生4096个ID序号),snowflake生成的ID整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由datacenter和workerId作区分),并且效率较高。经测试snowflake每秒能够产生26万个ID。

5、动态字段的表的设计思路。
如商品表:这里面是把商品的属性和数据先拆分为两部分,把一类商品“共性”的属性放在tb_spec表里面,与tb_category表的
三级类目关联起来,并且tb_spec表里面可以抽象出一类商品共有的属性和私有属性两部分。然后把数据信息放到tb_sku和tb_stock里面,用用tb_spu与tb_category表关联起来。最终通过tb_category这个纽带信息可以把商品的属性的数据结合到一起。

猜你喜欢

转载自blog.csdn.net/weixin_40682142/article/details/88357482