Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.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
Mysql 关于从用户处获取最新帖子的可伸缩性的问题有人在关注:两种不同的实现_Mysql_Design Patterns_Database Design_Relational Database_Innodb - Fatal编程技术网

Mysql 关于从用户处获取最新帖子的可伸缩性的问题有人在关注:两种不同的实现

Mysql 关于从用户处获取最新帖子的可伸缩性的问题有人在关注:两种不同的实现,mysql,design-patterns,database-design,relational-database,innodb,Mysql,Design Patterns,Database Design,Relational Database,Innodb,我有两种不同的实现来检索用户的投票,我想知道哪一种实现适合于更具可伸缩性的数据库。首先我将向您展示这些表,然后是两个实现 投票表 CREATE TABLE `poll` ( `id` int(1) unsigned NOT NULL AUTO_INCREMENT, `creator_id` int(1) unsigned NOT NULL, `date_created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `question` varcha

我有两种不同的实现来检索用户的投票,我想知道哪一种实现适合于更具可伸缩性的数据库。首先我将向您展示这些表,然后是两个实现

投票表

CREATE TABLE `poll` (
`id` int(1) unsigned NOT NULL AUTO_INCREMENT,
`creator_id` int(1) unsigned NOT NULL,
`date_created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`question` varchar(255) NOT NULL,
`num_of_responses` int(1) unsigned DEFAULT NULL,
`num_of_answers` enum('2','3','4','5') NOT NULL,
PRIMARY KEY (`id`),
KEY `creator_id` (`creator_id`),
KEY `date_created` (`date_created`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

repoll表-这两种实现都需要

CREATE TABLE `repoll` (
`repoller_id` int(1) unsigned NOT NULL,
`poll_id` int(1) unsigned NOT NULL,
`date_created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
KEY `repoller_id` (`repoller_id`),
KEY `poll_id` (`poll_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

下表

CREATE TABLE `following` (
`follower` int(1) unsigned NOT NULL,
`followee` int(1) unsigned NOT NULL,
KEY `follower` (`follower`),
KEY `followee` (`followee`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

用户_提要表-仅在第二次实现时需要

CREATE TABLE `user_feed` (
`user_id` int(1) unsigned NOT NULL,
`poll_id` int(1) unsigned NOT NULL,
`repoller_id` int(1) unsigned DEFAULT NULL,
`date_created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
KEY `user_id` (`user_id`),
KEY `date_created` (`date_created`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

第一个实现:不需要user_feed表,但是查询在计算上似乎比实现2中的查询要昂贵得多

SELECT P.id, P.creator_id, P.date_created
FROM
following f JOIN
(
    SELECT id, creator_id, date_created
    FROM poll
    UNION ALL
    SELECT poll_id, repoller_id, date_created
    FROM repoll
) AS P(id, creator_id, date_created)
ON f.followee=P.creator_id
AND f.follower=23
ORDER BY P.date_created DESC
LIMIT 120;
第二个实现:需要user_提要表和repoll表。每次有人发布/重新发布某个内容时,我都会向user_提要表添加一条记录。将为海报的每个追随者添加记录。比如说,我只为user_提要表中的任何特定用户保留120条记录。如果进行了post,并且用户在user_提要表中已经有120条记录,则删除该用户最早的记录并将其添加到repoll表中;新的一个取代了它的位置。如果一个用户请求的记录多于用户提要表中的记录,那么第一个实现将用于检索多余的记录

SELECT uf.poll_id, p.creator_id, uf.repoller_id, uf.date_created
FROM
user_feed uf JOIN poll p
ON uf.poll_id=p.id
AND uf.user_id=23
ORDER BY date_created DESC;

展开原始查询时,该查询似乎正在查找:

  • 由23人创建的民意测验
  • 由23个
  • 由某人创建的民意测验,随后是23次
  • 由某人创建的repolls,后跟23
假设“follower”中的行有限制,23不能是他自己的跟随者(即follower=followere时不允许有行)

并且还假设用户不能在同一准确时间重新调用相同的轮询,也就是说,(poll\u id,creator\u id,created\u on)元组在repll中是唯一的

(可能还有其他一些我还没有确定的情况…)

它看起来像四个不同的集合:

1) 由23人创建的民意测验

 SELECT p.id
      , p.creator_id
      , p.created_on
      , NULL AS repoller_id
   FROM poll p
  WHERE p.creator_id = 23
  ORDER BY p.created_on DESC LIMIT 80
2) 23日前重新发售

 SELECT p.id
      , p.creator_id
      , r.created_on
      , r.repoller_id
   FROM poll p
   JOIN repoll r
     ON r.poll_id = p.id
  WHERE r.repoller_id = 23
  ORDER BY r.created_on DESC LIMIT 80
3) 由某人创建的民意测验,随后是23次

 SELECT p.id
      , p.creator_id
      , p.created_on
      , NULL AS repoller_id
   FROM poll p
   JOIN following f
     ON f.followee = p.creator_id
    AND f.follower = 23
    AND f.follower <> f.followee  -- only needed if we don't disallow 23 to follow 23
  ORDER BY p.created_on DESC LIMIT 80
 SELECT p.id
      , r.creator_id
      , r.created_on
      , r.repoller_id
   FROM poll p
   JOIN repoll r
     ON r.poll_id = p.id
   JOIN following f
     ON f.followee = r.repoller_id
    AND f.follower = 23
    AND f.follower <> f.followee   -- only needed if we don't disallow 23 to follow 23
  ORDER BY r.created_on DESC LIMIT 80
在“following”表中,进行唯一约束,例如

ALTER TABLE `following` ADD PRIMARY KEY (follower, followee) 
不是针对此查询,而是针对系统中可能使用的其他查询

CREATE UNIQUE INDEX following_UX1 ON following (followee_id, follower_id)
并在“following”表的singleton列上删除(现在是冗余的)索引


还考虑添加适当的外键约束。

< P>实现1可以改进:
SELECT  P.id, P.creator_id, P.date_created
    FROM  following f
    JOIN (
          ( SELECT  id, creator_id, date_created
                FROM  poll
                ORDER BY  date_created DESC
                LIMIT  120
          ) UNION  ALL 
          (  SELECT  poll_id, repoller_id, date_created
                FROM  repoll
                ORDER BY  date_created DESC
                LIMIT  120
          )
         ) AS P   ON f.followee=P.creator_id
      AND  f.follower=23
    ORDER BY  P.date_created DESC
    LIMIT  120;

poll and repoll need:  INDEX(creator_id, date_created)
说明:在大多数情况下,看似冗余的
顺序依据。。LIMIT..
子句实际上是一种优化。在
中,在
联合
中选择
,它将最小化联合将创建的临时表中要存储的行数。临时表的行数不超过2*120行;如果表有数百万行,这一点很重要。外部查询还需要子句,以便将子列表混合在一起,并将结果缩减到所需的120

改进索引并允许“覆盖索引”:

说明:我假设
follower
followee
的组合是“唯一的”,因此可以是
主键。这样做的性能优势在于,给定跟随器的所有跟随器都位于相邻行中,反之亦然。您最初拥有的要慢得多,因为它必须首先查看索引,然后读取数据以获取这两个字段。我给你的是“覆盖”和“聚集”

你的第二种口味不应该有限制吗

uf
需要
索引(用户id、创建日期)


至于你最初的“哪一个”问题。。。我不认为第二个查询做了正确的事情。

id对性能有致命影响<代码>输入(选择…
对性能有致命影响。请注意,您需要在
SELECT
周围设置参数。将
中的
重写为
连接
;然后我们可以进一步讨论可伸缩性。还提供了
showcreatetable
。正如Rick James所指出的,MySQL优化器可以生成一些可怕的计划,其中包括或条件。通常,我们使用连接操作可以从查询中获得更好的性能。但这一切都取决于可用的索引,以及查询是否能够有效地使用索引,或者MySQL是否因为一个列被包装在一个函数中而不能使用索引。从性能可伸缩性的角度来看,这两个选项我都不喜欢。但乍一看,第二个查询似乎有更好的机会获得合理的访问计划,有合适的索引可用。。。联合操作需要使用文件排序操作来标识和删除重复项。UNION ALL set运算符不执行该操作。为了提高性能,如果不需要识别和删除重复项,请使用UNION ALL。在这两种情况下,要组合的集合的列数和列的数据类型需要匹配。不要用单引号括起标识符。单引号将字符串文字括起来。而内联视图被转换为派生表,这可能会对大型集合造成性能损失。@RickJames-Ok,完全升级了查询。准备好开始讨论实现的可伸缩性了吗?另一种选择是,如果我们在“下表”中为每个创建者id设置了行,使得创建者id跟随自己,并且每个报告者id也跟随自己,那么我们可以消除查询1和2,只使用查询3和4,取消跟随者跟随的限制。耶稣基督。这这太神奇了。你一定是超人或smn。现在就把它通读一遍,我要花一段时间来破译它-新手。但是谢谢你。。。很多我会在处理完之后再给你回复;特别是如果我有任何问题,我们真的需要看看解释,看看预期
CREATE UNIQUE INDEX following_UX1 ON following (followee_id, follower_id)
SELECT  P.id, P.creator_id, P.date_created
    FROM  following f
    JOIN (
          ( SELECT  id, creator_id, date_created
                FROM  poll
                ORDER BY  date_created DESC
                LIMIT  120
          ) UNION  ALL 
          (  SELECT  poll_id, repoller_id, date_created
                FROM  repoll
                ORDER BY  date_created DESC
                LIMIT  120
          )
         ) AS P   ON f.followee=P.creator_id
      AND  f.follower=23
    ORDER BY  P.date_created DESC
    LIMIT  120;

poll and repoll need:  INDEX(creator_id, date_created)
CREATE TABLE `following` (
  `follower` int unsigned NOT NULL,
  `followee` int unsigned NOT NULL,
  PRIMARY KEY(`follower`, followee),
  INDEX      (`followee`, follower)
) ENGINE=InnoDB DEFAULT CHARSET=latin1