需要数据库架构疯狂的最佳方法

时间:2012-02-06 21:02:29

标签: php mysql architecture

我们正在为我们的创业公司建立一个调度系统。

这只是一个普通的,除了我们愿意实施的“自动查找”功能。 LAMP架构。没什么特别的。

这就是数据库的外观。三个主要表格:

  • 办公室(id,start_time,stop_time)
  • 人物(id,office_id,start_time,stop_time)
  • 时间表(id,people_id,start_time,stop_time)

start_time / stop_time是TIMESTAMPS。

表不需要这样。这只是我们现在拥有的东西。

办事处表具有办公室的开启/关闭时间。这张桌子可能每个办公室大到365天,因为每天的开/关时间不一样。请注意,它可能多达1000个办事处。这使得表中大约有365,000条记录。

有加入/离开时间。这显然比办公室更具限制性。同样,一年中的每一天,人们都可以有不同的访问时间。每个办公室约有50人。这使得1000个办事处* 365天* 50名员工= 18,250,000条记录。

时间表是谁会见谁。每个人最多可以有10次会议/天。是的,在这一点上,这个表中很容易产生182.5百万行。

除了号码之外没什么奇怪的。该应用程序需要做的是:给办公室,见面人和持续时间,显示前5个日期。

据我们所知,这个应用程序将完全杀死我们的服务器。我们迫切希望能够实现这一目标。我们首先想到的是“这根本不可能”。但是嘿!一切皆有可能在软件中,不是吗?

PS:如果有人想出一个让应用程序可行的更好的方法,我们真的欣赏它。

非常感谢阅读。希望一些铁杆程序员可以帮助我们。

更新

出于测试目的,我们创建了两个完全相同的表:

会议&办公室(id,profesional,start,stop)。

ID是主要的,其余是BTREE索引。 SQL是这样的(100%不起作用):

SELECT a.profesional, a.stop AS desde, Min(b.start) AS hasta 
FROM meetings AS a 
  JOIN meetings AS b 
    ON  a.profesional=b.profesional 
    AND a.stop < b.start 
WHERE a.profesional = 1 
  AND b.profesional = 1 
GROUP BY a.start 

UNION 

SELECT m.profesional, MIN(m.start), MIN(j.start) 
FROM offices m 
  JOIN meetings j 
    ON  j.profesional = m.profesional 
WHERE j.profesional = 1 
  AND m.profesional = 1 

UNION 

SELECT m.profesional, MAX(j.stop), MAX(m.stop) 
FROM offices m 
  JOIN meetings j 
    ON  j.profesional = m.profesional 
WHERE j.profesional = 1 
  AND m.profesional = 1 

ORDER BY desde ASC

我们所做的是以下内容。仅添加1个办公室,240天。每天有8次会议,总共约2000行。执行此类查询需要2.6(!)秒。查询错了吗?它可以重写吗?

2 个答案:

答案 0 :(得分:6)

如果您有一个人,那是否已经减少了考虑减少50000倍的计划行数?如果您只考虑给定的办公室,办公室行数也将减少到几百。正确的索引可以立即找到这些行。

此外,人们是否真的提前安排了一整年的会议,或者您更有可能在未来一两个月内只拥有一个完整的数据库?如果您的主数据库出现性能问题,您始终可以将旧数据移动到存档中。

此外,根据“最多”的估计,很容易认为太大了。您应该尝试确定每个办公室在平均上会有多少人以及他们每天在平均上会有多少次会议。 “每天最多10次会议”可能很容易变成“通常每天两次”。当然,取决于我们正在谈论什么样的业务。

不要忘记减去周末。它们占全年的2/7。

答案 1 :(得分:0)

您的应用程序似乎需要一个关键查询。找到由

定义的区间
 (OfficeOpenIntervals INTERSECT PeopleAtOfficeIntervals) MINUS ScheduleIntervals

并在某个日期附近或之后搜索这些间隔。

使用适当的索引并限制查询(仅搜索一个人,接下来的60天等)可能会没问题。处理时间间隔操作很棘手,但您可以使用各种索引和方法来编写查询。


另一个选项(如果您通过索引测试并找不到有效的方法)是拥有一个单独的AvailableSlots表,当没有预定的约会时,该表将填充一个人所在的所有可用天数办公室(即OfficeOpenIntervals INTERSECT PeopleAtOfficeIntervals)。然后,每次在Schedule中添加约会时,此AvailableSlots表中的相应行将被删除,更新或分成两行,这些行将存储计划安排的人员的剩余可用间隔会议。

因此,显示前5个可用日期的查询只需要在此表中搜索。

这不是规范化的解决方案,并且必须通过存储过程维护完整性(对于所有操作,例如添加的时间表,离开办公室的人员,启动等)。最初的人口也需要时间和空间 - 但你不必在桌子上居住一百年。可能只需几个月,可以在以后完成其他人群(每月或每年一次或在需要时)。