我需要为以下场景构建数据库:
我将有一个拍卖输入流,我想为拍卖中的项目制作价格直方图(即他们通常会去的等等)。
输入流类似于:
{['item_id': 1, ... 'price': 123, ...],
['item_id': 1, ... 'price': 124, ... modifiers: [1, 2, 3],
['item_id': 1, ... 'price': 125, ... modifiers: [100, 150, 500...],
['item_id': 2, ... 'price': 200, ...],
...}
您可能已经注意到,item
不仅包含一些id
,还包含modifiers
。可以把它想象成可以用额外的东西修改的汽车(例如AC,电子窗等)。
存储此信息的最有效方法是什么?基本上我想要的是每个可能发生的组合unique id
。没有必要随时存储它,但如果有这种组合的拍卖,并且该组合尚不存在,那么就创建它。
我想到了类似的东西:
base_item:
id
modifier:
id
item:
id (autonumber)
base_item_id
item_modifications:
item_id (FK item.id)
modification_id (FK modifier.id)
item_price_history:
item_id (FK item.id)
price
time
此设置可能有效。问题是,想象一下,我每天都有数亿次这样的拍卖(即拍卖信息每20分钟更新一次,平均每次拍卖200万次)。
我希望能够快速执行以下操作:INSERT INTO item_price_history VALUES (some_item_id, some_price, now())
但是为了做到这一点,我需要找到some_item_id
。我知道base_item_id
和modifiers
(来自拍卖本身),但我认为这样做的次数相当昂贵吗?
即,伪代码:
for a in auctions:
base_item_id = a['item_id']
modifiers = a['modifiers']
price = a['price']
actual_item_id = some_query(base_item_id, modifiers) #expensive. Can be avoided?
insert_into_histogram(auctual_item_id, price) #expensive but necessary I think
我在这个设计中是否有一些明显的错误?
答案 0 :(得分:0)
您描述的架构是教科书解决方案。
但哇,这将是一个与之合作的野兽。据我了解,每次添加价格记录时,您都必须找到具有该确切参数集的项目记录:不多也不少。如果不存在此类项目记录,则必须创建项目记录。只有这样才能添加价格记录。
虽然我认为应该非常小心非规范化,但在这种情况下我会非常想要反规范化。也就是说,在我看来,在实践中,项目记录的关键是基本项目ID和修饰符的组合。我很想创建一个"修饰符字符串"通过将所有修饰符的代码或ID串联在一起而形成。当然要可行,他们必须按照规定的顺序串联起来,就像你不能同时拥有" 1,2"和" 2,1"。但是你可以很容易地找到所需的项目记录:只需要一个构建连接修饰符字符串的函数,然后选择其中base_item_id = @base和modifiers = @modifiers的项目。如果未找到,请创建记录和所有关联的修饰符记录。
我强烈倾向于将此修饰符字符串与单个修饰符记录一起冗余,但是像这样串联在一起的数据很难处理。我的意思是,如果您有一个像您描述的教科书架构,并且有人想知道带空调的汽车的价格,那么很容易从price.item中选择*(从项目连接修改器中选择id) modifier.item_id = item.id其中modifier.name =' AC')。但是尝试在连接的字符串上执行此操作,例如AC的ID是" 17"。选择blah blah,其中modifier_string喜欢'%17%'不起作用:它会找到117和171等等。喜欢'%,17,%'没有工作,因为如果它是第一个或最后一个,它将无法找到它。等等。这就是为什么我经常告诉人们不要像这样将数据串起来:创建单独的记录。但是,如果最常见的用例是您希望记录具有特定的修饰符组合,则创建冗余修饰符字符串是合理的非规范化。 (这是我第一次打字,我不小心输入了“道德败坏”,这可能是弗洛伊德的失误。)