2

我正在使用 Firebird 2.1,我正在寻找解决此问题的最佳方法。

我正在编写一个日历应用程序。不同用户的日历条目存储在一个大日历表中。每个日历条目都可以有一个提醒集——只有一个提醒/条目。

从统计上看,随着时间的推移,日历表可能会增长到数十万条记录,而提醒会少得多。

我需要不断地查询提醒。

哪个是最好的选择?

A)将提醒信息存储在日历表中(在这种情况下,我将查询数十万条 IsReminder = 1 的记录)

B)创建一个单独的 Reminders 表,其中仅包含设置了提醒的日历条目的 ID,然后使用 JOIN 操作查询这两个表(或者可能在它们上创建一个视图)

C) 我可以在 Reminders 表中存储所有关于提醒的信息,然后只查询这个表。缺点是需要在两个表中复制一些信息,例如为了显示提醒,我需要知道事件的开始时间并将其存储在提醒表中 - 因此我要维护两个具有相同值的表。

你怎么看?

还有一个问题:Calendar 表将包含多个用户的日历,仅由 UserID 字段分隔。由于只能有4-5个用户,即使我在这个字段上放了一个索引,它的选择性也会很差——这对于一个有几十万条记录的表来说是不好的。这里有解决方法吗?

谢谢!

4

3 回答 3

2

这三种选择各有利弊。最佳选择取决于您未提供的详细信息。一般来说,只要您设置的索引允许正确的检索策略,就不必太担心从十万个条目中选择三个或四个条目。如果不了解索引,那么无论您做出三个选择中的哪一个,您都可能会遇到麻烦。

如果是我,我会选择 B。我还会将提醒的任何属性存储在提醒表中。

要非常小心您是单独通过 EventId 还是通过 (UserId, EventId) 来识别事件。如果您选择后者,您应该为 Event 表使用复合主键。不要太担心复合主键,尤其是 Firebird。
如果您声明复合主键,请注意声明 (UserId, EventId) 与声明 (EventId, UserId) 的后果不同。它们在逻辑上是等价的,但是这两种情况下自动生成的索引的结构会有所不同。

这反过来会影响查询的速度,例如“查找给定用户的所有提醒”。

同样,如果是我,我会避免选择 C。在模式中引入有害的冗余会带来在更新数据时进行一些非常仔细的编程的责任。否则,您最终可能会得到一个数据库,该数据库将同一事实的相互矛盾的版本存储在数据库的不同位置。

而且,如果您真的想知道对性能的影响,请尝试所有三种方式,加载测试数据,并进行自己的基准测试。

于 2010-11-19T12:43:26.170 回答
0

我认为您需要创建真实的、虚假的用户数据,并使用您希望运行的一些典型查询来衡量差异。

索引、查询优化和您需要的查询结果类型会产生很大的不同,因此在不了解更多信息的情况下很难说什么是最好的。

于 2010-11-19T12:14:42.510 回答
0

选择选项 (A) 时,您应该

  • 提供关于“IsReminder”的索引(或 IsReminder、UserId 的组合索引,只要最适合您的预期查询)
  • 确保您的查询使用此索引

如果您为每个要存储的提醒存储多个布尔标志(例如,在事件发生前应通知用户的分钟数),则选项 B 比 A 更可取。但是,您应该猜测在您的程序中您必须多久将两个表连接起来。

如果可以,请避免选项 C。如果您不想对所有三种情况进行基准测试,我建议根据描述的情况从 A 或 B 开始,并且您选择的解决方案可能会足够快,所以您不要不得不为其他情况而烦恼。

于 2010-11-19T14:31:42.617 回答