一、SPU和SKU的作用
SPU和SKU是电商产品具有的两个重要概念。在电商网站设计中,它对应了一件商品在数据库表中的具体存储方式。抛开数据库来描述某一件商品,自然不需要额外加入这两个比较复杂的概念,但是考虑到电商系统中对商品信息的调用非常频繁,而数据的展现方式又各式各样,因此如果不对商品信息在数据库中存储方式进行合理设计,可能会导致数据库查询复杂化、页面请求变慢等问题。对前端而言,SPU、SKU可以对商品描述进行合理分级,便于在不同页面根据需求展示不同详细程度的产品信息;对后端而言,SPU、SKU可以统一和规范化产品的数据库设计,减少在管理商品(增删改查)时数据库的开销。
SPU和SKU的定义及他们之间的关系
- SPU全称Standard Product Unit,即标准化产品单元。简单理解就是某一种产品。
- SKU全称Stock Keeping Unit,即库存量单元。即具体的一件商品。
这两个概念字面意思上区分较为模糊,他们是在不同层次上对商品进行描述,我们可以这么理解:
标准化产品单元(SPU):标准化,即被广泛认知的的东西。在市场中我们买卖东西,我们会说某某品牌的xx产品如何如何,而不会去说某某品牌的xx产品xx颜色xx尺寸的产品如何如何。就好比手机发布会中,说我们今年推出了一款新的手机,型号为iPhone11,而不会说我们今年推出了iPhone 11 128G 玫瑰金、iPhone 11 128G 深空灰等等。标准化,也可以理解为对描述产品的详细程度上的一种标准,但需要注意的是这个标准是对产品的最小粒度描述。也就是说不同的SPU就是不同的产品了,如iPhone 11和iPhone x,虽然都是iPhone ,但是普遍认为iPhone 产品的最小粒度在型号上,因此他们就是两个产品了。
库存量单元(SKU):顾名思义就是库存商品单元,是要具体往外出售 的物品。SPU告诉了我们一个物品是什么东西,SKU则告诉了我们这个物品是一件具有什么特征什么规格尺寸当前是否还有库存的东西。
注意我上面的描述中,非常谨慎地使用了产品和商品两个词。个人理解,产品对应市场,商品对应顾客(和销售)。例如常说的,“9月国内手机市场排行第一名被OPPO A9拿下”(产品/spu),“我在xx商城抢购了个国行iphone x,黑色128g的,买的时候就剩x台了”(商品/sku)。简言之:
iPhone XR —— SPU
iPhone XR 黑色 128G —— SKU
我们可以从天猫和京东两个巨头产品的商品详情页来更加深入地认识到SPU和SKU的应用。
先来看看天猫Apple Store天猫官方旗舰店上展示的iPhone XS,然后大家留意当切换不同规格时页面标题和商品详情有什么变化:
其实无论我在iPhone XS这个商品下怎么切换规格,商品标题和商品详情都是不变的,所以天猫是以SPU形态来展示商品的。
我们再来看看京东的展示形态:
发现没有?每切换一个规格,商品标题是会跟着变化的。所以,京东是以SKU形态来展示商品的。上面的分析,有没有帮助大家更好地认识SPU和SKU的区别呢?再简单补充一个经典例子好了:
还记的我们在小卖部买矿泉水吗?
怡宝、百岁山,算是两个不同的SPU
百岁山大瓶3元、小瓶1.5元这就是百岁山这个SPU下的2个SKU
说了这么多,相信大家对SPU及SKU掌握的差不多了,下面拿京东为例,分析京东商城SPU与SKU是如何设计的。
1、三级分类-数据结构设计
这里我建了一张三级分类表【category】,表结构为:
2、商品属性-数据表设计
而上图中,SPU的规格与包装界面又做了一个分组,所以需要建立一张规格分组表【attribute_group】:
与之对应的则是规格表,即商品属性表【attribute】表结构如下:(attribute 9 10 11 12为销售属性,绑定SKU;其它为基本属性(固定不变的),绑定SPU)
既然规格表与规格分组表都有了,那么就需要建立一张关联表【attribute_attrgroup_relation】:
3、SPU相关数据表设计
接下来就需要设计商品表了,即SPU表【spu_info】
一件商品的商家肯定是需要附带图片的(注意富文本图文介绍放在spu_info表了,这里的图片存放商品的一些展示图)
【spu_images】
上文中讲到了商品属性(基本属性,销售属性),所以设计SPU,必然要考虑到SPU基本属性的设计,表结构如下【spu_attribute_value】
4、SKU相关数据表设计
【sku_info】由于SPU与SKU是一对多的关系,该表主要针对单个SPU可以实现添加多个SKU,每个SKU都有单独的默认图片,标题、副标题、价格等。
不同的SKU会对应一组不同的图片,所以需要建立SKU图片表【sku_images】
京东商城可以看出,当我们选黑色,左侧图集是一套黑色;选白色左侧图集即为白色。
上文中讲到了商品属性(基本属性,销售属性),与SKU对应则是销售属性,同理需要建立SKU销售属性表【sku_sale_attribute_value】
SPU基本属性和SKU销售属性都放到了attribute表,根据attr_type区分即可。
至此一套SPU、SKU基础数据结构就设计完成,实际项目中可能还会有其它场景,比如多商户,品牌,库存,积分等,根据实际需求具体开发即可。这里只结合SPU、SKU应用到电商网站的单品上架流程为:
要注意的是,基于SKU方式来管理产品时,产品的价格、库存和图片等信息必然是放在产品SKU表中处理的,和订单、购物车等表的关联,也是通过产品SKU表,而不是SPU产品表。至于产品表,实际上是一个总的业务汇总和外部关联表,但实际销售的并不是它。有些网站(京东)做的更细些,会就每个产品的SKU生成独立的URL(伪静态),从SEO方面考虑,每个产品SKU拥有独立的链接对收录和排名会更有优势,可以考虑~
二、参考京东商城详细讲解商品数据库设计
围绕商品设计表
之前也写过类似的数据库设计方案,这一篇是为大家详细讲解参考京东商城围绕商品怎么来设计数据库,需要关注的细节很多,对字段进行详解,结合功能实现分析每一个字段设计的意义
大家看完这篇文章后可以看看前面四篇文章电商项目数据库设计方案,跟这一篇有点不同,之前是大多是参照苏宁易购来设计的
我们在设计数据库的时候,大多都是按照我们自己的实际需求来设计,提供这几篇仅为大家参考学习,能够举一反三参与到项目实战中,希望大家可以学到东西,同时,文章内容如果有错误的位置希望大家可以指正,共同学习。
接下来我们就言归正传,开始设计表
分类表
左侧菜单栏,即显示的商品分类,分类表我们应该设置哪些字段,我们可以参照京东商城思考下:
首先作为关系型MySQL数据库,我们先定下通用字段,id、create_time、update_time这三个字段。逻辑删除字段看大家需求,我这里是自己做demo,就没有设置逻辑删除字段了,is_delete boolean类型,之前也写过仿照苏宁易购设计过数据库,大家可以参考着看,仅供学习使用。
看上图,我依次在菜单里面框出三个,在分类表中我们如何对菜单进行表示,字段名如何设置,很简单,设置成level1、level2、level3三个字段分别表示就可以了,level1表示一级菜单,level2表示二级菜单,level3表示三级菜单,但是想想,我们在实际业务中,如果我们开发一个商城以后有亿级用户,想添加其他的分类后,是不是要加level4、level5·····,这样设计就有点不灵活了
所以我们可以这样设计,设计一个parent_id 用来表示父类目id进行关联,顶级类目就是0,满足可扩展性,而且字段也不冗余,符合三范式设计,什么是数据库设计三范式,https://blog.csdn.net/weixin_42437102/article/details/106422548 不了解的同学可以看看这篇文章。
在设计一个is_parentid用来表示是否是父id,如果不是父id,肯定就是最后一次菜单,这里我不说是三级菜单,可能我们以后会进行扩展
给一个sort字段进行权重分配,排序指数,指数越小越靠前,这里就设计好了分类表。
品牌表
设计数据表,我们依旧先列出通用字段,id、create_time、update_time
截取京东页面
从上图我们可以看出,品牌设计也不怎么复杂,我们先看最上面,所有品牌,首字母表示,所有我们设计一个letter字段,用来表示品牌的首字母,可以用来做搜索
继续往下看,我们能看到什么?无非就会品牌的logo和名称了吧,那就设计name字段表示名称,image字段表示品牌的logo。还有没有什么?
逻辑删除也可以设置,这个放在关联关系表来说!
品牌分类表
前面我们已经分析出了商品分类表和品牌表,他们之间有什么关系,我们这个阶段来屡屡
首先我们还是回到京东首页,也就是我们在设计分类表的时候截取的京东那张图片,对边点击一个三级分类,我这里点的手机,是不是看到的是品牌表这里的图片,也就是说,一个分类下有多个品牌,如:(手机:有华为手机,苹果手机,小米手机···)
接下来看一张图:
华为品牌下也有很多分类,所以一个品牌下也有很多分类
即分类表与品牌表是多对多的关系,多对多设计中间表
但是,你可能会发现,这张表中并没有设置外键约束,似乎与数据库的设计范式不符。为什么这么做?
- 外键会严重影响数据库读写的效率
- 数据删除时会比较麻烦
在电商行业,性能是非常重要的。我们宁可在代码中通过逻辑来维护表关系,也不设置外键。
如果使用逻辑删除是否可以解决这个问题,大家可以思考下。
商品参数表
商品参数表也是我们围绕商品进行表设计的一个必不可少的表设计,但是参数表改如何设计呢?按照我们的正常思维,一个商品有很多参数,比如一个手机,有品牌、产品名称、机身长度、机身重量、CPU、内存等等一系列,我们分别设计成字段,一张表也就几十个字段,但是想想,这样做会有什么不妥,首先,我们设计数据库是设计一个全品类的电商平台,商品有很多种,我们打开京东看看,手机的规格与包装
还有很多很多,如果都设计一张参数表,可想而知是不妥的吧
但是我们发现,虽然不同商品,规格不同。但是同一分类下的商品,比如都是手机,其规格参数名称是一致的,但是值不一样。
也就是说,商品的规格参数应该是与分类绑定的。每一个分类都有统一的规格参数模板,但不同商品其参数值可能不同。
因此:
规格参数的名称(key)与值(value)应该分开来保存一个分类,对应一套规格参数模板,只有规格参数key,没有值
一个分类对应多个商品,每个商品的规格值不同,每个商品对应一套规格的值
所以我们引入参数组与参数表
值我们暂且先不管,新增商品时,再来填写规格参数值即可,我们先思考规格参数模板(key)该如何设计。
规格数据首先要分组,组内再有不同的规格参数
一个分类规格模板中,有多个规格组
每个规格组中,包含多个规格参数
从面向对象的思想来看,我们规格参数和规格组分别是两类事务,并且组与组内参数成一对多关系,因此可以有两个类分别描述他们,那么从数据库设计来看,也就对应两张不同的表:
规格组:tb_spec_group
一个商品分类下有多个规格组
规格参数:tb_spec_param
一个规格组下,有多个规格参数
大家接下来要思考的就是: 描述规格组需要哪些属性?
因为商品分类表与规格组表是一对多的关系,一个商品分类里面有多个组,所以在商品规格组表里面要有商品分类id关联起来
所以字段可以设置为以下:
id 规格组自增id
category_id 商品分类id
name 组名
create_time 创建时间
update_time 更新时间
描述规格参数需要哪些属性?
规格组表与与规格参数表也是一对多的关系,即一个组有多个参数,所以需要关联商品分类id,规格组id。想清楚上面的问题,就知道表该怎么设计了。
参数组表
还是老套路:固定的三个字段,id、create_time、update_time
组名:name,因为一个商品分类下有多个规格参数组,所以一对多的关系,设计category_id关联实现一对多
规格参数表
固定三个字段我们不需要过多的解释,这是我们的套路:id、create_time、update_time。
category_id、group_id 一个商品分类有多个规格参数组,一个规格参数组有多个规格参数
name 参数名也好解释
看着这个图片,我们自己来模拟设计下SPU表
id 主键
c_id 分类ID
brand_id 品牌ID
name 商品名称
description 描述
spec 规格
after_service 售后服务
comment 评价
似乎并不复杂.
再看下SKU,大家觉得应该有什么字段?
id: 主键
spu_id: 关联的spu
price: 价格
images: 图片
stock: 库存
颜色?
内存?
硬盘?
sku的特有属性也是变化的,不同商品,特有属性不一定相同,那么我们的表字段岂不是不确定?
sku的这个特有属性该如何设计呢?
首先我们应该了解sku特有属性为何?
顾名思义,特有属性就是特有的,所有商品各自持有的,比如商品的内存,不同手机内存不一样,有4G、6G、8G、16G…,颜色有红色、绿色、黑色等等,
那么是不是就是说我们的sku就是跟商品分类有关系,在我这里,SKU特有属性是跟商品规格参数有关系的,我们还是截取京东页面来看看,如下图
颜色—>对应五种
内存—>对应三种
这都是在参数规格中可以看到的,点击哪一种,下面的参数就跟着变化。SKU特有属性是商品参数规格的一部分
也就是说,我们没必要单独对SKU的特有属性进行设计,它可以看做是规格参数中的一部分。这样规格参数中的属性可以标记成两部分:
spu下所有sku共享的规格属性(称为通用属性)
spu下每个sku不同的规格属性(称为特有属性)
回一下之前我们设计的规格参数表,是不是有一个字段,名为generic,标记通用和特有属性。就是为了这里使用。
这样以来,商品SKU表就只需要设计规格属性以外的其它字段了,规格属性由之前的规格参数表来保存。
但是,规格属性的值依然是需要与商品相关联的。接下来我们就来看看到底怎么设计
SPU表
与我们前面分析的基本类似,但是似乎少了一些字段,比如商品描述。
我们做了表的垂直拆分,将SPU的详情放到了另一张表:tb_spu_detail
这张表中的数据都比较大,为了不影响主表的查询效率我们拆分出这张表。
需要注意的是这两个字段:generic_spec和special_spec。
SKU表
总结:
我们设计了哪几张表,有什么关系
分类表: tb_category
品牌表: tb_brand
分类品牌表:tb_category_brand
规格组表: tb_spec_group
规格参数表:tb_spec_param
SPU表: tb_spu
SPU详情表: tb_spu_detail
SKU表: tb_sku
关系:
一个分类有多个品牌,一个品牌属于多个分类,所以是多对多
一个分类有多个规格组,一个规格组有多个规格参数,所以是一对多
一个分类下有多个SPU,所以是一对多
一个品牌下有多个SPU,所以是一对多
一个SPU下有多个SKU,所以是一对多
注:部分图片来自于网络,若有雷同请评论留言