首页 > BAT面试题,求帮忙分析下这个数据库表有什么问题

BAT面试题,求帮忙分析下这个数据库表有什么问题

面试题有这样一个表,表示订单,面试官问这个表你觉得有什么问题,该怎么解决

id name number price total_price
1 ip5 5 5000 25000
2 ip6 4 6000 24000


看起来这个表示存放订单详细数据的,起个名字叫Order。 那么ID,Name应该在另外一个table里。假设叫Product,
Product 中
ID,Name

Order 中
ID, number, price

table中ID是FK,指向Product table, totle_price应该不需要。


这个事情很大程度上看实务逻辑而定。我们考虑现实中订单的一般特性:

  1. 订单总是大量客户订少量货品,多个订单中货品名称频繁重复是理所当然的

  2. 一张订单可能含有多个商品

  3. 总价格是间接数据

那么这个表格的逻辑,从数据库范式的角度来看,就有以下的问题需要纠正:

不过数据库范式这个东西并非越高越好,太高的范式确实冗余少了,但反而教条难以维护。所以对数据库范式的贯彻其实总是到某个程度为止(不要过度设计)。

并且实际应用中为了性能的关系,保留冗余数据作为缓存更是必要的手段。——但话说回来,缓存就是缓存,绝对不允许和实际数据列,存在一星半点的误解、混淆、看错的可能。

只要有1个人,不用多,任何1个人能够产生这种误会,那么就是失败,不能找任何借口。

在这个案例中,如果nametotal_price为了减少数据库查询压力而缓存,那么至少应该改名叫cache_namecache_total_price并放在表格最后。

其实更优的办法是把所有待缓存数据序列化之后,用BINARY/BLOB类型存成cache_serialized一列。直接搞个人类不可读,省去一切麻烦。


补充:我曾经胡扯过一个“数据一致性墨菲定则”——如果一个系统中,允许实际数据在不同位置出现2次,那么数据的一致性迟早必然被破坏。

所有性质的缓存,都是一个付出冗余和破坏数据一致性的代价,来换取性能的选择。所以这个选择中最重要的原则就是:只允许实务数据推翻缓存,反向是决不允许的。
(你希望遭遇数据不一致的时候,是原始数据都搞不清是哪个了,还是只需根据原始数据重刷一次缓存?)

这也就是上边坚持数据库中搞缓存时,必须100%明示缓存列,不容忍任何误解的理由。


total_price 总金额, 这个无需存入字段 number*price 即可, 这是一个沉余字段, 当然这得看具体的业务逻辑, 不过就算是业务逻辑中需要也可以通过 number*price 计算得出.
令, 细看的话, 不知到这个数据是什么用意, 理论上来说 price 字段不应该是 int 型, 但是从这个给出的数据来开, price 是 int 这是不合逻辑的

【热门文章】
【热门文章】