我正在寻找一种有效的方法来存储在事件期间一起发生的对象集,这样我就可以每天在它们上生成聚合统计数据。
举一个例子,让我们想象一个跟踪办公室会议的系统。对于每次会议,我们会记录它的长度以及它在哪个房间。
我希望无论是按人还是按房间分析统计数据。我不需要跟踪单个会议(所以没有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
我还能做什么?
答案 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 +时间戳)搜索时。这在以下的多索引部分中有更多解释:
答案 1 :(得分:0)
通过拒绝单独存储会议(和相关对象),您将丢失原始信息源。
除非您定期记住您可能需要稍后提问的所有潜在每日(或每月或每周或......)汇总的广泛列表,否则您将无法弥补这种数据丢失!
相信我,这将是一场噩梦......
答案 2 :(得分:0)
如果人数不变且不是很大,那么您可以为每个人分配一个列是否存在,并将房间,日期和时间存储在另外3列中,这可以消除字符串分裂问题。
同样根据你的问题的性质,我首先要感觉你需要将ID分配给所有房间,人员等。不需要DB中的长重复字符串。还尝试减少任何字符串操作,并使用每列中的单个数据来提高交叉性能。您还可以在表中存储所有人的排列并为其分配ID,然后在实际日期和时间表中使用其中一个ID。但是所有技术都需要人或房间保持不变。
答案 3 :(得分:0)
我不明白您是否在设计时知道所有“问题”,或者在开发/制作期间可以添加新问题 - 这种方法需要始终保留所有数据。
如果您知道所有问题,那么它似乎是经典的“银行系统”,它会每天重新计算数据。
我怎么想。
您可以使用可缩放的map / reduce算法。
答案 4 :(得分:0)
你无法避免存储原子事实如下:(会议室,人员,持续时间,一天),这可能只是当同一个人在同一个房间里多次见面时的弱合并同一天。也许这在你的办公室里发生了很多事情:)。
使群组具有可比性是一个有趣的问题,但只要你总是把成员字符串组成相同,你就可以用字符串比较来做。然而,这不是“正常”。为了规范化,你需要一个关系表(多对多)并从你的查询集中组成一个临时表,以便它快速加入,或使用“IN”子句和计数聚合来确保每个人都在那里(你会看到)当你尝试时我的意思。)
我认为你可以得出会议室使用的会议记录,因为会议不应该重叠,所以总和会有效。
为了提高存储效率,请使用整数键来查找查找表。在查询解析期间取消引用整数,或者如果您感觉传统的话,只使用好的旧连接。
无论如何我都会这样做:)。