为了尽可能好地描述问题,我将详细介绍实际情况: 该站点将允许用户添加IP以监控RBL。在这样做的过程中,我一直在思考不同的方法来构建数据库,以尽可能优化大型IP块的效率,同时仍然可行。
该项目建立在Laravel之上,我已经建立了一个包含以下内容的数据库结构:
表-A
包含有关我们监控的IP的信息。
- id(auto inc,primary)
- name(varchar,128)监视器的友好名称
- ip(varchar,16)要监控的IP
- 电子邮件(varchar,128)通知电子邮件
- 通知(tinyint,1)通知切换
- 时间戳
-
表-B
包含有关我们监控的RBL的信息。
- id(auto inc,primary)
- url(varchar,255)监视器的URL
- 有效(tinyint,1)切换我们是否主动检查
-
table_a_b
一个数据透视表,用于维护每个RBL的状态。
- table_a_id(int,10) table_a上id的外键
- table_b_id(int,10) table_b上id的外键
- 列出(tinyint,1)此RBL上是否列出了IP
- 已通知(tinyint,1)我们是否已通知用户
所以当前的工作方式是,在添加IP时,它会将IP添加到table_a,并将(number of rows in table_b * number of IP's)
添加到数据透视表中。虽然添加它并不需要那么长时间 - 我看到的问题是,添加一个/ 24个IP(256个IP)跟踪(当前)87个RBL会创建总计 22,272个记录。这是一个/ 24。 A / 22(1024 IP)将是89,088条记录。对于单个用户来说,这是一个相当大的数量,我可以看到它如何快速破坏数据库性能。
我想到的替代方法是在listed_on
上保留一个名为table_a
的列,它是列出它们的任何RBL的列表。该行将包含{{1}行的内容。 1}} - 这很简单,可以用PHP解析。尽管如此,对于大量用户,我可以看到用大量的字符串处理来达到PHP性能。
我在这里错过了一个明显的解决方案,还是这两个(或许特别是后者)最好的选择?
干杯!
答案 0 :(得分:2)
直接的关系设计(而不是table_a_b(ip, rbl, ...)
)是表listed(ip, rbl)
“ip IP列在rbl RBL上”和notified(ip, rbl)
“用户已经注意到ip IP列在rbl上RBL”。关系表用于保存从某些特定于表的谓词(由列参数化的句子模板)构成真正的命题(语句)的行。对于一列或多列的每个可能值应包含一行的表很少见。
是否应该使用组合这些表的设计取决于您的谓词以及将它们应用于可能出现的所有情况所遵循的约束。例如,如果通知仅发生在列出的IP-RBL对上,则最好是ip_rbl(ip, rbl, notified)
“IP IP在rbl RBL中,NOTIFIED是用户是否已被通知”。 (这里的权衡是更小的表格和更多的联接,而不是更少的大表和更多的搜索。)
PS Pivot表通常不适合操纵&查询数据与不透明的数据进行比较。它们可以适合格式化最终输出到人类或在数据和元数据之间移动。见this news post。 (我认为你的数据透视表是不透明的,因为布尔列名不是数据值,即使它是IP-RBL上的总表。)