【问题标题】:How to store sets of objects that have occurred together during events?如何存储在事件期间一起发生的对象集?
【发布时间】:2013-08-04 01:12:45
【问题描述】:

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

举个例子,让我们想象一个跟踪办公室会议的系统。对于每次会议,我们都会记录它持续了多少分钟以及在哪个房间举行。

我想按人和房间细分统计数据。我不需要跟踪单独的会议(所以没有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 在每个会议室中的 MEETING TOGETHER 花了多少分钟? Bob、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

我还能做什么?

【问题讨论】:

  • 所以,澄清一下,你有一个 bajillion “会议” 正在发生,所以你每天汇总它们。这意味着您在房间交叉口人交叉日花费了几分钟(我们称之为 R U P U D)。您希望 R U (P1 交点 P2 交点 P3) U D 以一种不必存储每个会议的方式...
  • 没错!如果我们存储了 meeting_ids,我们可以只获取 UNIQUE meeting_ids,然后查找每个信息的信息,但这将是 MySQL 汇总的大量记录。
  • 这些查询集是固定的还是可以改变的?我的意思是,当 Julia 和 Bob 不在这个会议室时,它会不会像 find 一样。我认为会议 ID 在这里并不重要,因为我们可以结合使用时间和董事会会议室来获得独特的会议。
  • 您需要提供更多信息:您预计有多少个会议室,有多少人?您以什么粒度进行查询?只是按天汇总? “共度时光”已经包含了会议的含义,因此无论如何您都在隐式存储此信息。

标签: database database-design data-structures analytics


【解决方案1】:

您的问题有点不清楚,因为您说您不想存储每个单独的会议,但是您如何获取当前的会议统计信息(日期)?此外,即使有很多记录,只要有正确的索引,任何表都可以非常快。

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

employee_id, room_id, date (as timestamp), time_in_meeting

员工ID外键到员工表,房间ID键到房间表

如果你索引员工 id、房间 id 和日期,你应该有一个非常快速的查找,因为 mysql 多列索引从左到右,这样你就可以获得索引(员工 id、员工 id + 房间 id 和员工 id + 房间 ID + 时间戳)何时进行搜索。这在多索引部分有更多解释:

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

【讨论】:

    【解决方案2】:

    拒绝单独存储会议(和相关对象),您将失去最初的信息来源。

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

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

    【讨论】:

      【解决方案3】:

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

      另外,根据您问题的性质,我觉得首先您需要为所有房间、人员等分配 ID。无需在数据库中使用长重复字符串。还可以尝试减少任何字符串操作,并使用每列中的单独数据来获得更好的交叉点性能。您还可以将所有人的排列存储在一个表中并为他们分配一个 ID,然后在实际日期和时间表中使用其中一个 ID。但所有技术都需要人或房间保持不变。

      【讨论】:

        【解决方案4】:

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

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

        我是怎么想的。

        1. 您的房间、人数、天数等​​似乎有限。
        2. 每天收集记录数据,每天一张表。只需一个事件、一个数据库行、您需要的所有信息(字段)。
        3. 在“午夜”开始使用一些 crone 脚本分析数据。
        4. 更新人员、房间等的统计信息。只需增加 Bob 在 xyz 房间等中花费的小时数。满足您的所有需求。
        5. 由于分析的数据有限且在您分析(压缩)它们时相对较小,因此您的系统还可以包含各种查询,因为索引相对较小等。

        您可以使用可扩展的 map/reduce 算法。

        【讨论】:

          【解决方案5】:

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

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

          我认为您可以得出会议室正在使用的会议记录,因为会议不应重叠,因此可以计算总和。

          为了提高存储效率,对所有带有查找表的内容都使用整数键。在查询解析期间取消引用整数,或者如果您感觉传统,则只使用旧的连接。

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2012-04-07
            • 2015-01-25
            • 1970-01-01
            • 1970-01-01
            • 2021-05-22
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多