MySQL表组织和优化(Rails)

时间:2011-03-09 21:50:26

标签: mysql ruby-on-rails optimization

过去几个月我一直在学习Ruby on Rails,没有任何编程经验。最近,我一直在考虑数据库优化和表组织。我知道有很多关于这个主题的书,但我通常会以实例/我的方式学习。

这是一个假设的情况:

假设我正在建立一个拥有250,000名成员(用户)的利基社区的社交网络。用户可以参加活动。假设有50,000个过去/现在/将来的事件。与Facebook活动非常相似,用户可以参加任意数量的活动,活动可以有任意数量的与会者。

在数据库中,会有一个用户表和一个事件表。不知何故,我必须在用户和事件之间创建一个关联。我可以在users表中创建一个“events”列,这样每个用户行都会包含一个事件ID哈希,或者我可以在events表中创建一个“参与者”列,这样每个事件行都会包含一个用户ID哈希。

然而,这些解决方案似乎都不理想。在用户的个人资料页面上,我想显示与之关联的事件列表,如果我在事件表中包含“与会者”列,则需要扫描50,000个事件行以获取所述用户的用户ID。同样,在事件页面上,我想显示事件的与会者列表,如果我在users表中包含“events”列,则需要扫描250,000个用户行以查找所述事件的事件ID。

选项3将创建第三个表,其中包含每个事件的与会者信息 - 但我不知道这将如何解决任何问题。

这些不是问题吗? Rails使得访问所有这些信息变得容易,但我想我担心规模。完全有可能我低估了现代数据库/服务器等的速度和处理能力。扫描250,000个用户行需要多长时间才能获得特定事件ID - 10ms? 100ms的? 1,000ms?我想那不是那么糟糕。我只是过度思考这个吗?

3 个答案:

答案 0 :(得分:3)

这是用户和事件之间典型的多对多关系。

您需要第三个表(比如UserEvent或更好的 UserAttendsEvent 或只是出席),每个用户和用户参加的每个事件都有一行。

因此它至少会有一个userID和一个eventID,它们都是User和Event表的外键。

在这两个字段上添加索引可能会对您的查询有利,因为您计划拥有数百万行。

UserEvent也可能有其他数据,例如用户注册活动时,她在活动中花的钱,是否喜欢,等等。

问题是,每一行都有关于“出席”的信息。参加过的人(userID),参加过的人(eventID),他到达的时间,花费的时间等等。你不想把这些信息都放在用户表和事件表中。

由于您担心性能,我将添加一个数据库如何搜索特定查询的示例。让我们说我们想找到所有参加(或计划)2011年7月雅典U2音乐会活动的用户,并和我一样过生日。

database plan:
1. use eventTitle index in table Event 
     to find that the event has id 47519 
   (good for us that we have created such an index).
2. use eventID index in table Attends 
     to find all (469) userids that have attended eventid 47519.
3. use the userid index in table User
     to find all the info of the 469 users.
4. search the info (birthdate) from those
     to keep only those (3) that have birthday July 24th.
     (we have not created any index that can be used here)

因此,数据库只访问磁盘以搜索索引并读取我们需要的数据。不读取所有数据并在其中搜索。

在更复杂的查询中,或者因为查询需要表中的所有数据,或者如果尚未创建所需的索引或某些索引无用,或者db查询优化器决定它更快,它可能会扫描表或部分然后搜索数据。但是,如果已经定义了“正确的”索引(适合您的计划使用),查询将会很快。

答案 1 :(得分:0)

“在用户个人资料页面上,我想显示与之关联的事件列表,如果我在事件表中包含”与会者“列,则需要扫描50,000个事件行以获取所述用户的用户ID 。“

如果每个用户ID都不是唯一的密钥,则必须扫描50,000个事件行,我当然希望这样做。如果每个用户ID都是唯一键,那么它很快。同样,事件表:每个事件都有一个唯一的ID,也是它唯一的密钥。

你必须让这些ID成为唯一的钥匙,否则你就会穿上运动鞋。

- 皮特

答案 2 :(得分:0)

老问题,但在我正在寻找其他事情时添加细节。

在Rails中,这是通过模型中的“has_and_belongs_to_many”子句来处理的,该子句为您创建了多对多分辨率表。这里的文档:http://guides.rubyonrails.org/association_basics.html

使用解析实体,数据库实际上并不扫描整个表以查找信息,它使用b-tree索引来查找所需的特定行 - 因此多对多可以直接修复你正在提出的性能问题。