扩展数据,减少加载时间,让我的网站主机满意的最佳方式

时间:2011-02-23 19:38:24

标签: php mysql database facebook scaling

对于Facebook应用程序,我必须在MySQL数据库中存储用户的朋友列表。我的数据库请求此列表,与其他数据等进行比较。

目前,我将这个朋友列表存储在我的用户表中,将朋友的uid放在一个'text'字段中,并带有'|'作为分隔符。例如:

  

ID - UID - NAME - FRIENDS => 1 - 123456789 - John Doe - 987654321 | 123456 | 765432

我的PHP文件请求此行并通过爆炸该字段(“|”)来提取朋友列表。这一切都运行正常,每1000个用户大约有5MB磁盘空间。

现在出现问题:

对于额外功能,我还需要保存用户朋友的姓名。我可以用不同的方式做到这一点:

1)将此数据保存在额外的表格中。例如:

  

ID - UID - NAME => 1 - 1234321 - Jane Doe

如果我需要ID为1234321的朋友的姓名,我可以从此表中请求该名称。然而,问题是该表将继续增长,直到Facebook上的所有用户都被索引(> 5亿行)。我的虚拟主机不会喜欢这个!这样的表将占用大约25GB的磁盘空间。

2)另一个解决方案是扩展用户表中保存的数据,方法是将名称添加到friends字段中的UID(使用额外的分隔符,让我们使用',')。例如:

  

ID - UID - NAME - FRIENDS => 1 - 123456789 - John Doe - 987654321,Mike Jones | 123456,Tom Bright | 765432,Rick Smith

对于这个解决方案,我必须改变脚本,添加另一个额外的爆炸(',')等。我不确定这需要多少额外的磁盘空间......但是数据没有得到这样容易处理!

3)第三种解决方案可以很好地概述所有数据,但会导致数据库变得庞大。在这个解决方案中,我们创建了一个朋友表,每个友谊都有一行。例如:

  

ID - UID - FRIENDUID => 1 - 123456789 - 54321

     

ID - UID - FRIENDUID => 3 - 123456789 - 65432

     

ID - UID - FRIENDUID => 2 - 987654321 - 54321

     

ID - UID - FRIENDUID => 4 - 987654321 - 65432

正如您在此示例中所看到的,它可以非常好地概述所有友谊。然而,有大约5亿用户,并且假设每个用户平均有300个友谊,这将创建一个包含150亿行的表。我的主人绝对不会那样......我认为这种表会占用大量的磁盘空间......

那么......如何解决这个问题呢?您如何看待,在Facebook上存储UID +用户朋友名称的最佳方式是什么?如何扩展这种数据?或者你有另一种(更好的)解决方案,而不是上面提到的三种可能性?

希望你能帮助我!

3 个答案:

答案 0 :(得分:3)

  

如果我需要朋友的名字   ID 1234321,我可以申请这个名字   从这张桌子。但是,问题   是这张桌子会继续增长,   直到Facebook上的所有用户都是   索引(> 5亿行)。我的虚拟主机   不会喜欢这个!这样的   表将占用约25GB   磁盘空间。

如果存储您需要的用户名称确实需要25GB,那么它需要25GB。你不能移动数据并期望它变小 - 而且表的开销不是 。相反,您需要专注于仅存储您实际需要的数据。 Facebook上的所有人不太可能使用您的应用程序(如果 的情况下,您不应该使用25GB空间的主机)。

因此,不是索引整个Facebook(无论如何都很难),只需存储与实际使用您的应用程序的人及其直接朋友相关的数据,这是一个小得多的数据集。

您提出的第一个解决方案是正确的方法;它消除了名称存储中的任何潜在冗余。

答案 1 :(得分:0)

我同意Amber,解决方案1将是存储此数据的最有效方式。如果您想坚持使用当前的方法(类似于解决方案2),您可能需要考虑将友谊数据存储为JSON字符串。它不会产生尽可能短的字符串,但它很容易解析。

保存数据:

$friends = array(
    'uid1' => 'John Smith',
    'uid2' => 'Jane Doe'
);

$str = json_encode($friends);

// save $str to the database in the "friends" column

要获取数据:

// get $str from the database

$friends = json_decode($str, TRUE);

var_dump($friends);

答案 2 :(得分:0)

我真的认为你应该选择第三种选择。为了扩展性,您可能希望这样做 使用第一种方法,你有很多冗余数据,因为如果1是2的朋友,2也是1的朋友。但是你存储两种关系。
这也使得1500亿行数不可能。这种情况最多可能是一半,因为关系表可以双向工作!! 因此第一个用户将在表中生成300行,但第二个用户(如果他是1的朋友)将只生成299.继续这样做,最后一个用户甚至不会生成关系行,因为它们都是已经在场了!
此外,当你想开始搜索某些关系时,第三个选项会快得多,因为你有一个int索引而不是fulltext索引,这可能会在存储和处理中节省另外50%速度。

如果您的应用程序将达到5亿用户,您将只需要获得更好的托管服务。