-1

这是一个有点长的问题,因为我想解释问题的所有细节。

系统描述

我们有一个来自外部系统的传入消息队列。消息会立即存储在例如 INBOX 表中。很少有线程工作者从表中获取作业块(首先用 UPDATE 标记一些消息,然后 SELECT 标记的消息)。工作人员不处理消息,他们根据消息命令将它们分派到不同的内部组件(称为“处理器”)。

每条消息都包含几个文本字段(最长的是 200 个 varchars)、几个 id 和一些时间戳等;总共 10-15 列。

每个处理消息的内部组件(即处理器)的工作方式不同。有些会立即处理消息,有些会触发一些长时间的操作,甚至通过 HTTP 与系统的其他部分进行通信。换句话说,我们不能只处理来自收件箱的消息,然后将其删除。我们必须使用该消息一段时间(异步任务)。

尽管如此,系统中的处理器并不多,最多 10 个。

消息都是内部的,即用户浏览它们、分页等并不重要。用户可能需要处理过的相关消息的列表,但这不是关键任务功能,因此它不必很快。有时可能会删除一些无效的消息。

重要的是要强调预期的流量可能会非常高——我们不希望因为糟糕的数据库设计而出现瓶颈。数据库是MySql。

决定

其中一个决定是不要为所有消息提供一个大表,其中有一些标志列将指示各种消息状态。想法是每个处理器都有表;并移动消息。例如,收到的消息将存储在 INBOX 中,然后由调度程序移动到某个例如 PROCESSOR_1 表,最后移动到 ARCHIVE 表。此类动作不应超过 2 个。W

在处理状态下,我们确实允许使用标志来指示特定于处理的状态(如果有)。换句话说,PROCESSOR_X 表可以跟踪消息的状态;因为当前正在处理的消息的数量将大大减少。

这样做的原因是不要对所有事情都使用一个 BIG 表。

问题

由于我们正在四处移动消息,我想知道这对于大容量来说有多昂贵。以下哪种情况更好:

(A) 将所有类似的表分开,就像解释的那样,并移动完整的消息行,例如从收件箱中读取完整的行,写入处理器表(带有一些附加列),从收件箱中删除。

或者

(B) 为了防止内容的物理移动,如何拥有一个只存储内容(并且仍然不是状态)的大 MESSAGES 表。如上所述,我们仍然有其他表,但它们只包含消息的 ID 和其他列。所以现在,当消息即将移动时,我们在物理上移动的数据要少得多——只是 ID。消息的其余部分始终未修改地保留在 MESSAGE 表中。

换句话说,一个小表和一个大表之间的 sql join 是否有惩罚?

感谢您的耐心等待,希望我足够清楚。

4

1 回答 1

0

解决方案 B 原因如下:

  1. 移动大量数据不会占用内存
  2. I/O 操作更少
  3. 数据库碎片更少

在表格列中使用标志:布尔字段(读取、存档、删除...)并适当地设置它们。另一个优化是在服务器不忙时推迟执行冗长/繁重的任务。这种优化不能由操作系统或数据库完成,因为它需要业务意识。

于 2013-03-07T00:21:06.570 回答