数据库设计:多个表与单个表

时间:2012-01-26 16:47:51

标签: mysql database scalability

我正在建立一个网站,其中有不同类型的项目,如博客,帖子,文章等。用户可以将他们中的任何一个设置为他/她的最爱。现在当我接近这个东西时,我有两个选择

  
      
  1. 为每种类型的对象创建一个用户收藏夹表。
  2.   
  3. 为所有用户创建所有类型对象的公用表。
  4.   

第一个结构的问题是我将不得不查询很多表来显示特定用户的收藏夹。但它可以让我轻松地将收藏夹分为不同的类别。

但是,如果我必须在一个页面上显示所有收藏夹并将它们全部合并,根据时间排序,那么这就变得困难了。但是如果我使用第二个模型,我可以很容易地获得最新的收藏夹,并且根据对象类型对它们进行分组并不困难,但是我会在一个大的桌面网站上进行分组。

这两种策略中哪一种更具可扩展性。

  

第一个需要多个数据库查询,第二个需要   需要一张大单桌。

如果有帮助,我正在使用MySql

3 个答案:

答案 0 :(得分:8)

您似乎已经知道了答案,但请记住,保持您设计的系统易于修改,因为商业模式总是随着时间的推移而变化,或者最终会失败(这是一种概括,但您明白了)。其中的一个必然结果是,如果你制作一个刚性模型,无论是快速还是慢速,它都是僵化的,变化会更难,最终用户也不会看到差异,因此不会实现金钱/幸福的变化,除非这是一个非常糟糕的变化。 你的问题不是技术问题,而是查询在引擎上工作的方式,而不是一个哲学问题,容易改变而不是表观速度。 问问自己,拥有标准化数据库的优势是什么?考虑一个干净的架构和设计,性能是当今世界中最少的问题,因为处理更便宜,存储也是如此。但设计很昂贵。 规范化是为了使系统不依赖于最后时刻的决策,而是依赖于结构化设计过程。 大表对于MySql来说并不是什么大问题,但它们对于维护,修改和扩展来说是一个大问题。它不只是添加一个列,而是关于数据本身的刚性结构。最终,您将只添加包含索引的列,这些索引将指向小表。无论如何,MySql将抄袭所有数据。 所以我会选择第一个,很多小桌子,多对多。

答案 1 :(得分:4)

我的网站上有这个设计。我的模块是:新闻,文章,视频,照片,下载,评论,测验,民意调查等。所有这些都在单独的表格中。我有一个喜欢的桌子,用户可以喜欢或不喜欢一个帖子(在你喜欢的情况下)。获得这些的查询并不复杂。

首先,大多数情况下我的表模块的结构都采用相同的方式:

  • ID
  • 标题
  • 含量
  • user_id(作者)
  • 日期

除了少数例外情况,有时标题被称为问题或没有内容列。这不会引起任何问题。

我喜欢的桌子设置如下:

  • ID
  • PAGE_ID
  • module_id(它来自哪个表...我有一个模块表,每个模块都有一个标题,关联的id,目录等)
  • post_id(对应于模块表ID)
  • user_id(喜欢或发帖的用户)
  • 状态(0 =喜欢,1 =不喜欢)
  • 日期(喜欢/不喜欢的时候)

模块表示例:

  • ID
  • 标题
  • 目录
  • post_type

实施例

id      title              directory         post_type
 1       News                news               news
 2     Episode Guide       episodes            episode
 3       Albums           discography/albums    album

基本上你的会有类似的设置,根据需要修改表格结构。

查询以获取特定用户的所有喜欢或收藏:

$getlikes = mysql_query("SELECT DISTINCT post_id, module_id, page_id FROM likes WHERE user_id = $profile_id ORDER BY id DESC LIMIT $offset, $likes_limit", $conn);
$likes = mysql_num_rows($getlikes);

if($likes == "0"){
echo "<br><Center>$profile_username does not have any liked posts at this time.</center><BR>";
}
else {
echo "<table width='100%' cellspacing='0' cellpadding='5'>

<Tr><th>Post</th><th align='center'>Module</th><th align='center'>Page</th><tr>";

while ($rowlikes = mysql_fetch_assoc($getlikes)) {
   // echo data

$like_page_id = $rowlikes['page_id'];
$like_module_id = $rowlikes['module_id'];
$like_post_id = $rowlikes['post_id'];


// different modules have different fields for the "title", most are called title but quotes is called "content" and polls is called "questions"
if($like_module_id == "11"){
$field = "question";
}
elseif($like_module_id == "19"){
$field = "content";
}
else{
$field = "title";
}





// FUNCTIONS
PostURL($like_page_id, $like_module_id, $like_post_id);
ModTitle($like_module_id);
ModTable($like_module_id);
ModURL($like_page_id, $like_module_id);
fpgURL($like_page_id);


$getpostinfo = mysql_query("SELECT $field AS field FROM $mod_table WHERE id = $like_post_id", $conn);
$rowpostinfo = mysql_fetch_assoc($getpostinfo);
$like_post_title = $rowpostinfo['field'];

// Using my "tiny" function to shorten the title if the module is "Quotes"
if($like_module_id == "19"){
Tiny($like_post_title, "75");
$like_post_title = "\"$tiny\"";
}


if(!$like_post_title){
$like_post_title = "<i>Unknown</i>";
}
else {
$like_post_title = "<a href='$post_url'>$like_post_title</a>";
}

echo "<tr class='$altrow'>
<td>$like_post_title</td>
<td align='center'><a href='$mod_url'>$mod_title</a></td>
<td align='center'>$fpg_url</td>


</tr>";

$altrow = ($altrow == 'altrow')?'':'altrow';

} // end while

echo "<tr><Td align='center' colspan='3'>";

// FUNCTIONS - Pagination links
PaginationLinks("$cs_url/users/$profile_id", "likes");

echo "</td></tr></table>";

} // end else if no likes

好的,你可能很难理解,因为我有很多自己的变量,但基本上它从likes表中获取模块id和post id,然后运行查询以获取帖子的标题和任何其他info我想要原作者。

我设置了“模块”功能,如果您为其提供了ID,则会返回模块的url或标题。

答案 2 :(得分:0)

因此,如果我没记错的话,您正在尝试创建一个Favorites表来收集用户喜欢的商品吧?如果是这样,您将至少需要两个表。

类型:资源的类型。

+----+---------+
| ID |  Name   |
+----+---------+
|  0 | blog    |
|  1 | post    |
|  2 | article |
|  3 | photo   |
|  4 | video   |
+----+---------+

收藏夹:收藏夹系统中最重要的部分,有点像关系图。

+--------+----------+--------------+
| UserID | TargetID | TargetTypeID |
+--------+----------+--------------+
|    941 |        1 |            0 |
|      6 |      935 |            1 |
|     26 |       51 |            4 |
|      7 |       87 |            2 |
+--------+----------+--------------+

帖子:示例帖子表,您可能也有BlogsPhotosAlbums表。

+-----+------------------+
| ID  |      Title       |
+-----+------------------+
|   0 | This is my post! |
|  51 | Oh, how are you? |
| 935 | Hello, world!    |
+-----+------------------+

现在,SQL查询可能是这样的(未经测试的):

-- Get the posts
SELECT p.*
FROM Posts p
LEFT JOIN Favorites f 
-- Which are favorited by the user 6
ON f.UserID = 6 
-- Also get the type id of the `post`,
-- so we can specify the favorite type of the favorite items
AND f.TargetTypeID = (
    SELECT ID 
    FROM Types
    WHERE Name = 'post'
)
-- Make sure we only get the posts which are favorited by the user.
WHERE p.ID = f.TargetID

使用上面的SQL查询,您可以获取由用户ID 6收藏的收藏帖子。

+-----+------------------+
| ID  |      Title       |
+-----+------------------+
| 935 | Hello, world!    |
+-----+------------------+