要记录一个用户的会员开通记录:按照范式的话,应该是将用户表和会员记录表分离出来,但是这样的话,每次查会员是否有效是不是都得去关联一次会员记录表了?如果直接在用户表页加一个截止时间的字段,那这样在查询的时候是不是会少一次关联,但这样岂不是违反了范式?
用户表:
id (用户 id )
expired_at (当前会员截止时间,是否需要这个字段?)
会员记录表:
id (记录 id )
uid (用户 id )
paid_at (支付时间)
expired_at (截止时间)
status (订单状态)
对于数据库设计有点迷糊,求各位指点迷津
1
feigle 2019-12-30 14:32:01 +08:00
下次来了个 vvip 的需求,你是不是得在用户表中再加一个字段 vvip_expired_at (当前 vvip 截止时间)?
|
2
lhx2008 2019-12-30 14:37:01 +08:00 via Android
从范式来说,用户表不需要任何 vip 有关的内容,vip 表也不需要任何订单相关的内容,想要快的话做个 vip 用户缓存就行了。
不过你在用户表插个过期时间也不是不行,只是你 vip 到时候还有别的信息要存的 |
3
encro 2019-12-30 14:43:57 +08:00
应该分成:
用户表(可以加截止时间,当前 vip 类型), 会员购买记录表(每次购买是一条记录), 这样就没有冲突了。 还可以避免没有过期重复购买的问题。 设计数据库的一个重要思考原则就是参考财务账单,任何操作都是一个单据(数据库记录),这个单据负责追溯发生了什么事,其他是否该冗余完全根据数据库性能来,去 TM 范式。 |
5
2379920898 2019-12-30 15:11:53 +08:00
看完 高性能 四五六章 =没苦恼
|
6
wangyzj 2019-12-30 15:41:35 +08:00
理论上订单表里面不应该有结束时间把
应该是一个 sku id 会员表里面是过期时间,这样性能会好一些 |
7
yrj 2019-12-30 16:32:01 +08:00 via iPad
其实吧,多一次关联,也慢不到哪去
|
8
kyuuseiryuu 2019-12-30 16:37:35 +08:00
你给数据库省事儿,就是给自己未来找事儿。
|
9
mahogany 2019-12-30 17:45:36 +08:00
为了性能可以部分违背范式,不过你要保证用户表上的会员截止日期恩能被正确地更新,缓存要同步。
|
10
yb3712590 2019-12-30 23:07:18 +08:00
当用户数和开通记录都上亿,且用户表用于生产需要频繁查询时,你可以单独新建用户快查表,加入需要高频检索的属性,每日凌晨计算并更新这个表。
否则没理由违反范式。 |
11
daozhihun 2019-12-31 09:32:36 +08:00
范式不是分解到越高越好,要根据实际情况取舍。
比如订单明细表可以算出总金额,但是通常情况还是会在订单表里搞一个 total 字段,即使这个字段是冗余的而且可能导致不一致的情况。 |