在我的Rails应用程序中,我有各种包含用户数据的数据库表。其中一些表有很多行(在某些情况下,每个用户最多有50万行),并且经常被查询。每当我查询任何表时,当前用户的user_id都在查询的某个位置--如果该表与用户有直接关系,或者通过连接(如果它们通过其他表关联),则直接查询该表。
为了更快的性能,我应该取消user_id并将它包含在每个表中吗?
以下是一个例子:
user_id
一个常见的昂贵查询是为特定用户选择所有的AddressesEnvelopes,即使我不需要这些表中的任何内容,我也可以通过连接地址或信封来完成这些任务。或者我可以复制这个表中的用户id。
这里有一个不同的场景:
信属于用户,user_id
属于recepient_id。
在接受者和RecepientOption中复制user_id是否有意义,即使我总是可以通过联系,通过信函获得它?
一些注意事项:
因此,我应该在每个表中包括user_id,以便在创建索引时使用它?那会不会是个糟糕的设计?
发布于 2009-12-24 10:39:40
我想指出的是,如果您愿意使用复合主键,则没有必要进行反错。AddressEnvelop案例的样本:
user(
#user_id
)
address(
#user_id
, #addres_num
)
envelope(
#user_id
, #envelope_num
)
address_envelope(
#user_id
, #addres_num
, #envelope_num
)(#表示主键列)
如果我能避免的话,我不是这个设计的粉丝,但是考虑到您说所有这些对象都绑定到一个用户的事实,这种类型的设计将使它相对简单地划分您的数据(逻辑上,将用户范围放在单独的表中,或者物理上使用多个数据库,甚至是机器)。
在这种设计中,另一件有意义的事情是使用聚集索引(在MySQL中,InnoDB表的主键是从聚集索引构建的)。如果确保user_id始终是索引中的第一列,则将确保每个表的所有数据都存储在磁盘上。当您总是使用user_id进行查询时,这是很好的,但是如果您使用另一个对象进行查询,则会影响性能(在这种情况下,复制就像您建议的那样可能是一个更好的解决方案)。
无论如何,在更改设计之前,首先要确保模式已经优化,并且外键列有适当的索引。如果性能确实是最重要的,那么您只需尝试几种解决方案并进行基准测试。
发布于 2009-12-24 10:28:29
只要你
( a)取得可衡量的性能改进
和
b)知道数据库的哪些部分是真正的规范化数据,哪些是冗余的改进
没有理由不这样做!
发布于 2009-12-24 10:37:41
实际上,您有衡量性能的问题吗? 500,000行不是很大的表。如果选择不是很复杂,而且列上有适当的索引,那么选择应该是合理的、快速的。
首先,我将查看是否存在慢速查询,并尝试使用索引优化查询。如果这还不够的话,只有这样我才会研究去正规化。
如果您不能通过其他方法实现所需的性能,那么您建议的反错操作似乎是合理的。只需确保您保持非规范化字段的最新。
https://stackoverflow.com/questions/1957734
复制相似问题