【问题标题】:Database design and join operations among database tables数据库设计和数据库表之间的连接操作
【发布时间】:2014-01-25 11:33:03
【问题描述】:

这个问题的主题是在我的网站上维护用户cmets。

我的网站上有大约 25000 篇文章(不同类别),每篇文章下面都有一个 cmets 部分。由于 cmets 的数量增加了 70,000 多篇,我决定根据文章的类别将文章分成不同的表格articles_of_type_category以及每个表对应的 cmets 表 article_category_comments,假设它会在未来提高性能(尽管目前它工作正常)

现在我有两个问题:

1) 是否应该划分数据库,否则如果表进一步增大,性能不会下降?

2)如果是,那么我在新数据库设计的连接操作 SQL 中存在一些问题。在每篇文章的 cmets 页面上,我会显示 cmets、发表评论的人的姓名和他的观点。

假设用户正在查看文章 3,因此我需要获取以下详细信息以显示在文章 3 的页面上

-------------------------------------------------------------------------------------------
serial#|  comment  | name_who_made_this_comment |  points  |  gold  |  silver  | bronze
-------------------------------------------------------------------------------------------
       |           |                            |          |        |          | 
       |           |                            |          |        |          |

通过加入这三个表

user_details

+----+--------+----------+
| id | name   | college  |
+----+--------+----------+
|  1 | naveen | a        |
|  2 | rahul  | b        |
|  3 | dave   | c        |
|  4 | tom    | d        |
+----+--------+----------+

score(这个表像stackoverflow一样存储用户积分)

+----+--------+------+--------+--------+---------+
| id | points | gold | silver | bronze | user_id |
+----+--------+------+--------+--------+---------+
|  1 |   2354 |    2 |      9 |     25 |    3    |
|  2 |   4562 |    1 |      9 |     11 |    2    |
|  3 |   1123 |    7 |      9 |     11 |    1    |
|  4 |   3457 |    0 |      9 |      4 |    4    |
+----+--------+------+--------+--------+---------+

comments(此表存储评论、发表评论的文章的 ID 和用户 ID)

+----+----------------------------+-------------+---------+
| id | comment                    |  article_id | user_id |
+----+----------------------------+-------------+---------+
|  1 | This is a nice article     |           3 |       1 |
|  2 | This is a tough article    |           3 |       4 |
|  3 | This is a good article     |           2 |       7 |
|  4 | This is a good article     |           1 |       3 |
|  5 | Please update this article |           4 |       4 |
+----+----------------------------+-------------+---------+

我尝试了类似的东西

select * from comments join (select * from user_details join points where user_details.id=points.user_id)as joined_temp where comments.id=joined_temp.u_id and article_id=3;

【问题讨论】:

  • 这个,“根据其类别articles_of_type_category将文章分成不同的表”,听起来很糟糕。我建议在您的 Article 表中对类别表和 categoryId 进行规范化设计。
  • @DanBracuk:如果您通过命名表和相应的列名来进行概述,那将非常有用
  • 您可以使用该子查询执行此操作,但您也可以使用 user_details 和 points 直接加入 cmets。我怀疑引擎会创建一个非常不同的查询计划,但尝试一下不会有什么坏处。

标签: mysql sql database database-design


【解决方案1】:

这是对此评论的回应,“@DanBracuk:如果您通过命名表和相应的列名来提供概述,那将非常有用”

 Table category
 categoryId  int not null, autoincrement  primary key
 category varchar(50)

示例类别可以是“童话”、“第一次世界大战”或“电影明星”。

 Table article
 articleId int not null, autoincrement  primary key
 categoryId  int not null foreign key
 text clob, or whatever the mysql equivalent is

由于该评论是对我对文章和类别的评论的回应,因此此答案仅限于此。

【讨论】:

    【解决方案2】:

    我会从一个包含文章和类别的表格开始。然后使用桥接表将两者链接起来。我的建议是索引桥接表中的类别。这样可以加快访问速度。

    表结构示例:

    CREATE TABLE Article (
     id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
     title varchar(100) NOT NULL 
      );
    
    INSERT INTO Article
        (title)
    VALUES 
    ('kljlkjlkjalk'),
    ('aiouiwiuiuaoijukj');
    
    CREATE TABLE Category (
      id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
      name varchar(100)
      );
    
    INSERT INTO Category
        (name)
    VALUES 
    ('kljlkjlkjalk'),
    ('aiouiwiuiuaoijukj');
    
    
    CREATE TABLE Article_Category (
      id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
      article_id int,
      category_id int
    );
    
    INSERT INTO Article_Category
        (article_id, category_id)
    VALUES 
    (1,1),
    (1,2);
    
    CREATE TABLE User_Details
        (`id` int, `name` varchar(6), `college` varchar(1))
    ;
    
    INSERT INTO User_Details
        (`id`, `name`, `college`)
    VALUES
        (1, 'naveen', 'a'),
        (2, 'rahul', 'b'),
        (3, 'dave', 'c'),
        (4, 'tom', 'd')
    ;
    
    CREATE TABLE Score
        (`id` int, `points` int, `gold` int, `silver` int, `bronze` int, `user_id` int)
    ;
    
    INSERT INTO Score
        (`id`, `points`, `gold`, `silver`, `bronze`, `user_id`)
    VALUES
        (1, 2354, 2, 9, 25, 3),
        (2, 4562, 1, 9, 11, 2),
        (3, 1123, 7, 9, 11, 1),
        (4, 3457, 0, 9, 4, 4)
    ; 
    
    CREATE TABLE Comment
        (`id` int, `comment` varchar(26), `article_id` int, `user_id` int)
    ;
    
    INSERT INTO Comment
        (`id`, `comment`, `article_id`, `user_id`)
    VALUES
        (1, 'This is a nice article', 3, 1),
        (2, 'This is a tough article', 3, 4),
        (3, 'This is a good article', 2, 7),
        (4, 'This is a good article', 1, 3),
        (5, 'Please update this article', 4, 4)
    ;
    

    试试这个:

    SQLFiddle Demo

    祝你好运。

    【讨论】:

      【解决方案3】:

      70000 个元素并不多。事实上,这个数字几乎为零。你的问题在于糟糕的设计。我有一个包含数百万条记录的表,当我向在后端执行复杂查询的应用程序服务器发出请求时,它会在不到一秒的时间内做出响应。所以你肯定在做次优设计。我认为详细的答案会占用太多的空间和精力(因为我们在您的问题上建立了完整的科学),这超出了本网站的范围,因此我选择为您指出正确的方向:

      1. 了解标准化(1NF、2NF、3NF、BCNF 等)并将其与您的设计进行比较。

      2. 了解索引和其他隐式优化

      3. 优化您的查询并最小化查询数量

      至于回答您的具体问题:不,您不应该“划分”您的桌子。您应该修复数据库架构中的结构错误并使用您的数据库优化算法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多