38 | 电商系统表设计优化案例分析
38 | 电商系统表设计优化案例分析
讲述:李良
时长14:59大小6.86M
核心业务
1. 商品模块
2. 购物车模块
3. 订单模块
4. 库存模块
5. 促销活动模块
业务难点
1. 不同商品类别存在差异,如何设计商品表结构?
2. 双十一购物车商品数量大增,购物车系统出现性能瓶颈怎么办?
3. 订单表海量数据,如何设计订单表结构?
4. 抢购业务,如何解决库存表的性能瓶颈?
5. 促销活动也存在抢购场景,如何设计表?
总结
思考题
赞 7
提建议
精选留言(22)
- -W.LI-2019-08-17外键关联,对表数据操作时,一锁锁好几张表。删除时还要做校验。影响性能
作者回复: 对的
51 - 张德2019-09-01老师好 请教一个问题 以前阿里面试官就问过这么一个问题 比如在订单表中缓存了商品的名称 后来这个商品改了名字了 那我原先在订单表中的字段应该怎么处理 或者是类似的订单表中缓存的字段名称发生了改变 希望老师可以解答 谢谢
作者回复: 订单表冗余了商品的名称,如果修改了商品名称,我们一般不会再去修改订单中的冗余数据了。 商品是有唯一标识的,商品的具体名称的修改,其实是不会影响到用户的体验,如果商品名称修改比较大,会影响到用户体验了,这个时候我们建议下架商品,上架一个新的商品。
共 3 条评论33 - 小橙橙2019-08-20老师,文中说的“通过大数据查询订单信息”这部分,能不能深入讲一下大数据实现的方案
作者回复: 收到
共 3 条评论9 - td9011052020-05-28比较好的方式是通过一个公共表字段来存储一些具有共性的字段,创建单独的商品类型表,例如手机商品一个表、服饰商品一个表。 老师您好,请问一下这里说的是只有商品类型表还是存在一个所有的商品的表,但是只存放通用字段,比如类型、库存、价格等?
作者回复: 对的,不通用的这些字段可以拼成json存在一个字段中,冗余在键值对数据库,也可以作为查询字段使用。
4 - better2019-09-11老师,以订单表为例,怎么简单理解什么叫水平分表,什么叫垂直分表呢
作者回复: 以订单的某个列作为hash,通过hash求余或一致性哈希算法来分表,例如 数据A和数据B,水平分表后就会放到两张表中; 垂直分表则是将一张表的一些列分开到另外一张表中,例如,订单表有 订单号、付款金额、付款时间等,如果将付款金额和付款时间单独为另外一张表,这种情况就是垂直分表。
4 - QQ怪2019-08-17逻辑复杂,且性能低下3
- 灿烂明天2019-08-23老师,你好,那逻辑上实现表的关联,具体怎么做才好呢?举个例子吧,谢谢
作者回复: 例如,订单表和详细订单表中,如果是物理关联的情况下,是以订单表的ID关联详细订单表外键orderID。 在逻辑上关联的意思就是,在没有任何业务操作的情况下,详细订单表依然有orderID字段,只是我们不需要再物理关联订单表ID了。一旦有业务操作,我们记得在业务层将两张表的操作关联起来,例如,删除主订单,此时记得删除详细订单表。
2 - 许童童2019-08-17外键对数据库性能有影响,比如保持数据的一致性,所以我们在程序层面保证数据的一致性,这样数据库的性能就会好很多。
作者回复: 对的,用逻辑关联来保证各个表数据的一致性。
3 - 老杨同志2019-08-17使用外键,在手工处理数据时特别麻烦。update数据要求先后顺序。程序在更新数据时多了外键约束检查也影响性能
作者回复: 是的,即麻烦又影响性能。
3 - 小笨蛋2019-08-18有两个疑问,第一:如果把订单表以用户id维度水平分表,商家要查看他们店的所有订单情况怎么办?第二:如果商品比较多,商品也需要分表的话,用户搜索商品怎么处理?商家的要看自己店的商品怎么办?
作者回复: 第一个疑问,商家的订单表可用冗余数据来实现,商家查看的一套数据存放在键值对数据库;第二个问题,如果商品数据量比较大,我们可将商品存放在Elasticsearch、Solr。
1 - 失火的夏天2019-08-17外键是一个强制性的约束,插入数据会强制去外键表里先查是否有这个数据。 更新删除的时候还得去获取外键数据的锁,并发性能下降,高并发情况还可能造成死锁。 使用外键,讲代码层的逻辑转移到了数据库中,数据库性能开销变大,性能容易产生瓶颈。 除了以上几个,好像还有在水平分表和分库情况下,外键是无法生效的。倒是我一直没理解是为什么。老师能说一下为什么吗?还有外键在如果存在在分库分表的系统中会有什么样的问题?展开1
- 学习学个屁2021-08-21公共字段那块,关系型数据库存json字符创比较好,也可以使用文档数据库Mongodb,但引入mongodb又增加了系统复杂性
- 青鸟飞鱼2020-11-05老师你好,为什么使用外键有时候会造成死锁?
- 怀草诗2020-04-22老师好,请问如果一张表后期数据量会很大,那应该怎么设计呢?
作者回复: 分表,如果考虑到后期再分表带来的数据迁移问题,考虑基于一致性哈希算法进行分表
- 6CYS2020-03-14老师好,“目前互联网公司一般建议逻辑上实现各个表之间的关联,而不建议使用外键来实现实际的表关联,你知道这为什么吗?”这句话说的是不加外键约束条件的意思吗?逻辑上实现各个表的关联是什么意思?
作者回复: 是的
共 3 条评论 - 月迷津渡2019-10-17说订单表需要提前用snowflake生成Id,我有点没太明白 首先第一点 如果原始变不用自增Id用UUID是不是就行了?(不考虑UUID长度问题) 第二主键Id与业务耦合是怎么来理解呢? 第三用最初的自增ID到左后snowflakeId变换的复杂点在哪呢?是不是先要先加列生成新ID,同时关联表也加上新ID,然后再删除主表的老ID和关联表的老ID?
作者回复: 我们在新建表时,DBA会要求innodb存储引擎的表中,默认需要配置自增主键ID,并且该主键ID耦合在业务中。使用自增主键主要是因为innodb中的主键索引是聚族索引,B+树中的叶子节点存储了行数据,数据记录本身被存于主索引的叶子节点上,同一个叶子节点内的各条数据记录按主键顺序存放,因此每当有一条新的记录插入时,MySQL会根据其主键将其插入适当的节点和位置。如果表使用自增主键,那么每次插入新的记录,记录就会顺序添加到当前索引节点的后续位置,当一页写满,就会自动开辟一个新的页。 如果使用非自增主键,由于每次插入主键的值近似于随机,因此每次新纪录都要被插到现有索引页得中间某个位置,此时MySQL不得不为了将新记录插到合适位置而移动数据,甚至目标页面可能已经被回写到磁盘上而从缓存中清掉,此时又要从磁盘上读回来,这增加了很多开销,同时频繁的移动、分页操作造成了大量的碎片,得到了不够紧凑的索引结构。 DBA要求自增主键ID不参与业务,主要考虑后续数据迁移的难度。
共 4 条评论 - 风轻扬2019-09-24老师,您文中提到的键值对数据库。是指的redis,memcache,这种吗?还是RocksDB、LevelDB这种呢?
作者回复: redis mongodb 以及es这些
- Demon.Lee2019-09-19比较好的方式是通过一个公共表字段来存储一些具有共性的字段,创建单独的商品类型表,例如手机商品一个表、服饰商品一个表。但这种方式也有缺点,那就是可能会导致表非常多,查询商品信息的时候不够灵活,不好实现全文搜索。 这时候,我们可以基于一个公共表来存储商品的公共信息,同时结合搜索引擎,将商品详细信息存储到键值对数据库,例如 ElasticSearch、Solr 中。 ------------------- 老师,这段话我没有理解透,能否再深入说说,谢谢了。没搞明白到底是一个表还是多个表。展开
作者回复: 一个公共表存储商品的共同信息,例如商品的sku 编码、价格、图片地址、商品类型等,这些字段都是所有商品都有的属性。 而一些分的比较细的属性,例如商品颜色、尺寸、材料、品牌等信息则可以存储在键值对数据库。
- 钱2019-09-15课后思考及问题 1:目前互联网公司一般建议逻辑上实现各个表之间的关联,而不建议使用外键来实现实际的表关联,你知道这为什么吗? 这是因为操作复杂,性能低下。操作的复杂性体现在操作时有先后顺序的约束,有对于外键检查的约束。性能低下主要是因为数据库本身也要去对应的表中检查外键是否合法,多做了一些事情必然更耗性能。 另外,我们使用数据库还有几条规则 1:不允许物理删除 2:每张表必须有id/isDel/status/createTime/createPin/updateTime/updatePin/ts这几个字段 3:表的查询操作要尽量简单 4:建表及改表结构必须经过架构师review 5:对库中核心表的操作留有操作历史记录,要知道谁?啥时候?操作了啥?展开
作者回复: 这几条规则已经是行业内的标准规则,值得借鉴
共 2 条评论 - 尔冬橙2019-08-28老师能不能讲一下设计表结构的时候的范式规则和反范式规则
作者回复: 这块比较理论,有什么不懂的可以细节问我