Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 类似于Twitter的帖子时间线的数据库结构和查询_Sql_Django_Database_Postgresql - Fatal编程技术网

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

Sql 类似于Twitter的帖子时间线的数据库结构和查询,sql,django,database,postgresql,Sql,Django,Database,Postgresql,我用Django标签发布这个问题,因为我在这个环境中工作,但实际上它更多的是一个普通问题:我想在Twitter上显示一些类似于我的时间线的东西,即我跟踪的所有人的帖子列表,按时间顺序排列 我的典型数据库结构如下所示: Table Name: Users Columns: UserID PK EmailAddress Password TableName: Friends Columns: UserID PK FK FriendID PK FK Tabl

我用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!):

这很有效-没问题!但是,这确实,因此不能缩放!让我们假设我们有一个繁忙的网站,我们给定的用户有2000个朋友,数据库中有大约一千万个帖子。在这种情况下,数据库查询将非常低效和缓慢

这可以用关系数据库如PostgreSQL或MySQL来解决吗?如果没有,例如Twitter是如何做到的

   SELECT p.*
     FROM Posts AS p
     JOIN (SELECT FriendID
             FROM Friends
            WHERE UserID = :given_user_id) AS f
       ON (p.UserID = f.FriendID)
规模更好。由于您已经标记了PK,所以您已经准备好了所有需要的索引

较短的版本:

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       |
+---+---+--------------------------+

您也可以按照自己的查询进行操作,它将起作用:

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

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

谢谢joanolo!我认为你的答案是正确的,因为你给出了一个完整的例子。其他答案同样正确。然而,我希望能有一个类似NoSQL数据库的更复杂的解决方案,因为
JOIN
仍然不够高效。我是Pixabay.com的首席开发人员,我们的PostgreSQL数据库越来越成为可靠的数据存储,而所有快速读取的数据都由Elastisearch服务器提供。它正在工作,但我想知道NoSQL数据库是否是另一种方式。Twitter或Facebook是如何做到这一点的?您需要从两个表中获取信息。你必须以这样或那样的方式加入他们。让数据库决定哪种方法最好。NoSQL数据库可以很好地存储整个文档(例如:一篇文章及其所有注释,它们总是一起显示)。执行连接通常不太好(这是您在这里想要的)。您可能只需要一个更快的数据库(更快的硬件、SSD磁盘、大量内存,以便将大部分数据放入RAM中,…)。确保你有所有合适的索引。你能发送一份执行计划吗?请注意Twitter和Facebook的做法:我真的不知道(我认为他们不会公开这些信息)。但我认为他们只是使用了一些技术,给了他们一个近似的解决方案。顺便问一下:拥有2000个朋友的用户现实吗?如果你的问题与朋友网络密切相关,你可能想看看(比如)。哦,图形数据库,从来没有听说过。对于这个用例来说,听起来是一个有趣的选项。谢谢-也谢谢你对NoSQL的解释!
SELECT
    *
FROM
    Posts
WHERE
    UserID in (SELECT FriendID 
                 FROM Friends 
                WHERE UserID = 1 /* whatever */ ) ;