如何存储在事件期间一起发生的对象集?

时间:2013-08-02 17:03:31

标签: database database-design data-structures analytics

我正在寻找一种有效的方法来存储在事件期间一起发生的对象集,这样我就可以每天在它们上生成聚合统计数据。

举一个例子,让我们想象一个跟踪办公室会议的系统。对于每次会议,我们会记录它的长度以及它在哪个房间。

我希望无论是按人还是按房间分析统计数据。我不需要跟踪单个会议(所以没有meeting_id或类似的东西),我想知道的是每日汇总信息。在我的实际应用程序中,每天有数十万个事件,因此单独存储每个事件是不可行的。

我希望能够回答以下问题:

2012年,Bob,Sam和Julie在每个会议室花了多少分钟(不一定在一起)?

使用3个查询执行此操作可能很好:

>>> query(dates=2012, people=[Bob])
{Board-Room: 35, Auditorium: 279}
>>> query(dates=2012, people=[Sam])
{Board-Room: 790, Auditorium: 277, Broom-Closet: 71}
>>> query(dates=2012, people=[Julie])
{Board-Room: 190, Broom-Closet: 55}

2012年,Sam和Julie在每个会议室共度多少分钟?鲍勃,萨姆和朱莉一起怎么样?

>>> query(dates=2012, people=[Sam, Julie])
{Board-Room: 128, Broom-Closet: 55}
>>> query(dates=2012, people=[Bob, Sam, Julie])
{Board-Room: 22}

2012年,每个人在董事会会议室花了多少分钟?

>>> query(dates=2012, rooms=[Board-Room])
{Bob: 35, Sam: 790, Julie: 190}

2012年,董事会会议室使用了多少分钟?

这实际上非常困难,因为总结每个人花费的分钟数的天真策略将导致严重的过度计算。但我们可以通过将数字分别存储为元人来解决这个问题任何人:

>>> query(dates=2012, rooms=[Board-Room], people=[Anyone])
865

我可以使用哪些好的数据结构或数据库来启用此类查询?由于我的应用程序的其余部分使用MySQL,我很想定义一个字符串列,其中包含会议中每个人的(已排序)ID,但此表的大小会很快增长:

2012-01-01 | "Bob"           | "Board-Room" | 2
2012-01-01 | "Julie"         | "Board-Room" | 4
2012-01-01 | "Sam"           | "Board-Room" | 6

2012-01-01 | "Bob,Julie"     | "Board-Room" | 2
2012-01-01 | "Bob,Sam"       | "Board-Room" | 2
2012-01-01 | "Julie,Sam"     | "Board-Room" | 3

2012-01-01 | "Bob,Julie,Sam" | "Board-Room" | 2

2012-01-01 | "Anyone"        | "Board-Room" | 7

我还能做什么?

5 个答案:

答案 0 :(得分:0)

您的问题有点不清楚,因为您说您不想存储每个单独的会议,但那么您如何获得当前的会议统计数据(日期)?此外,即使有大量记录,任何给出正确索引的表都可以非常快。

您应该能够使用像log_meeting这样的表。我想它可能包含类似的内容:

employee_id, room_id, date (as timestamp), time_in_meeting

员工id到employee表的外键,以及room表键到房间表

如果您索引员工ID,房间ID和日期,您应该快速查找,因为mysql多列索引从左到右,以便您获得索引(员工ID,员工ID +房间ID和员工ID) +房间ID +时间戳)搜索时。这在以下的多索引部分中有更多解释:

http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html

答案 1 :(得分:0)

通过拒绝单独存储会议(和相关对象),您将丢失原始信息源。

除非您定期记住您可能需要稍后提问的所有潜在每日(或每月或每周或......)汇总的广泛列表,否则您将无法弥补这种数据丢失!

相信我,这将是一场噩梦......

答案 2 :(得分:0)

如果人数不变且不是很大,那么您可以为每个人分配一个列是否存在,并将房间,日期和时间存储在另外3列中,这可以消除字符串分裂问题。

同样根据你的问题的性质,我首先要感觉你需要将ID分配给所有房间,人员等。不需要DB中的长重复字符串。还尝试减少任何字符串操作,并使用每列中的单个数据来提高交叉性能。您还可以在表中存储所有人的排列并为其分配ID,然后在实际日期和时间表中使用其中一个ID。但是所有技术都需要人或房间保持不变。

答案 3 :(得分:0)

我不明白您是否在设计时知道所有“问题”,或者在开发/制作期间可以添加新问题 - 这种方法需要始终保留所有数据。

如果您知道所有问题,那么它似乎是经典的“银行系统”,它会每天重新计算数据。

我怎么想。

  1. 好像你的房间,人数,天数等都有限。
  2. 每天收集一次记录数据,每天一张。只需一个事件,一个数据库行,所需的所有信息(字段)。
  3. 在“午夜”使用一些crone脚本开始分析数据。
  4. 更新人员,房间等的统计数据。只需增加Bob在xyz房间等所花费的小时数。所有您的要求都需要。
  5. 由于分析数据是有限的,并且在分析(压缩)它们时相对较小,因此您的系统也可以包含各种查询,因为索引相对较小等。
  6. 您可以使用可缩放的map / reduce算法。

答案 4 :(得分:0)

你无法避免存储原子事实如下:(会议室,人员,持续时间,一天),这可能只是当同一个人在同一个房间里多次见面时的弱合并同一天。也许这在你的办公室里发生了很多事情:)。

使群组具有可比性是一个有趣的问题,但只要你总是把成员字符串组成相同,你就可以用字符串比较来做。然而,这不是“正常”。为了规范化,你需要一个关系表(多对多)并从你的查询集中组成一个临时表,以便它快速加入,或使用“IN”子句和计数聚合来确保每个人都在那里(你会看到)当你尝试时我的意思。)

我认为你可以得出会议室使用的会议记录,因为会议不应该重叠,所以总和会有效。

为了提高存储效率,请使用整数键来查找查找表。在查询解析期间取消引用整数,或者如果您感觉传统的话,只使用好的旧连接。

无论如何我都会这样做:)。