数据库结构和类似Twitter的帖子时间轴的查询

时间:2017-01-03 22:34:06

标签: sql django database postgresql

我发布了一个带有Django标签的问题,因为我在这个环境中工作,但实际上它更多或是一般性问题:我想展示类似的东西我在Twitter上的时间表,即我按照时间顺序排列的所有人的帖子列表。

我的典型数据库结构如下所示:

Table Name: Users
Columns:
    UserID PK
    EmailAddress
    Password

TableName: Friends
Columns:
    UserID PK FK
    FriendID PK FK

TableName: Posts
Columns:
    UserID PK FK
    Content

如果我想检索给定用户的所有朋友的所有帖子,它看起来像这样(这不应该是有效的SQL!):

SELECT * FROM Posts WHERE UserID IN (LIST OF "Given user friends' IDs")

这有效 - 没问题!但是,这确实所以不缩放!假设我们有一个忙碌的网站,我们的给定用户有2000个朋友,数据库中有大约一千万个帖子。在这种情况下,数据库查询效率极低且速度慢。

这可以通过像PostgreSQL或MySQL这样的关系数据库来解决吗?如果不是,例如,做到了吗?

3 个答案:

答案 0 :(得分:3)

较短的版本:

SELECT
    Posts.*
FROM
    Posts 
    JOIN Friends ON Friends.FriendID = Posts.UserID
WHERE
    Friends.UserID = 1 /* change as needed */ ;

您可以查看:

CREATE TABLE Users
(
    UserID integer PRIMARY KEY,
    EmailAddress text,
    Password text
) ;

CREATE TABLE Friends
(
    UserID integer NOT NULL REFERENCES Users(UserID),
    FriendID integer NOT NULL REFERENCES Users(UserID),
    PRIMARY KEY (UserID, FriendID)
) ;

CREATE TABLE Posts
(
    PostID integer PRIMARY KEY,
    UserID integer NOT NULL REFERENCES Users(UserID),
    Content text
) ;

INSERT INTO Users 
VALUES 
  (1, 'a@b.com', 'pass1'),
  (2, 'b@b.com', 'pass2'),
  (3, 'c@b.com', 'pass3'),
  (4, 'd@b.com', 'pass4') ;

INSERT INTO Friends
VALUES 
   (1, 2),
   (1, 4) ;

INSERT INTO Posts
VALUES
    (1, 2, 'A post from User 2'),
    (2, 2, 'Another post from User 2'),
    (3, 3, 'A post from User 3'),
    (4, 4, 'A post from User 4') ;

你应该得到:

+---+---+--------------------------+
| 1 | 2 | A post from User 2       |
| 2 | 2 | Another post from User 2 |
| 4 | 4 | A post from User 4       |
+---+---+--------------------------+

答案 1 :(得分:1)

   SELECT p.*
     FROM Posts AS p
     JOIN (SELECT FriendID
             FROM Friends
            WHERE UserID = :given_user_id) AS f
       ON (p.UserID = f.FriendID)

更好地扩展。当你标记了你的PK时,你已经拥有了所有需要的索引。

答案 2 :(得分:1)

您也可以按照自己的QUERY进行操作:

SELECT
    *
FROM
    Posts
WHERE
    UserID in (SELECT FriendID 
                 FROM Friends 
                WHERE UserID = 1 /* whatever */ ) ;

这将扩展(在最新版本的mySQL或PostgreSQL中,它将生成与JOIN相同的执行计划)。