如何为我的网站帖子实施已查看的系统?

时间:2016-07-10 01:00:41

标签: mysql sql algorithm performance database-design

这是我目前的结构:

// posts
+----+--------+----------+-----------+------------+
| id | title  | content  | author_id | date_time  |
+----+--------+----------+-----------+------------+
| 1  | title1 | content1 | 435       | 1468111492 |
| 2  | title2 | content2 | 657       | 1468113910 |
| 3  | title3 | content3 | 712       | 1468113791 |
+----+--------+----------+-----------+------------+

// viewed
+----+---------------+---------+------------+
| id | user_id_or_ip | post_id | date_tiem  |
+----+---------------+---------+------------+
| 1  | 324           | 1       | 1468111493 |
| 2  | 546           | 3       | 1468111661 |
| 3  | 135.54.12.1   | 1       | 1468111691 |
| 5  | 75            | 1       | 1468112342 |
| 6  | 56.26.32.1    | 2       | 1468113190 |
| 7  | 56.26.32.1    | 3       | 1468113194 |
| 5  | 75            | 2       | 1468112612 |
+----+---------------+---------+------------+

这是我的问题:

SELECT p.*,
       (SELECT count(*) FROM viewed WHERE post_id = :id) AS total_viewed
 FROM posts p
WHERE id = :id

目前,我面临viewed表的大日期。那么我的表结构(或数据库设计)有什么问题?换句话说,我该如何改进呢?

像stackoverflow这样的网站有近1200万个帖子。每个帖子都查看了(平均) 500。因此viewed行的数量应为:

12000000 * 500 = 6,000,000,000 rows

Hah :-) ..老实说,我甚至无法读取该数字(顺便说一下这个数字会每秒增长)。那么stackoverflow如何处理每个帖子的查看次数?是否总是会根据每个帖子的count(*)计算viewed

1 个答案:

答案 0 :(得分:0)

在您拥有数百万行之前,您不太可能需要分区,redis,nosql等。与此同时,让我们看看我们能做些什么。

让我们从解剖您的查询开始。我看到WHERE id=...但没有LIMITORDER BY。让我们添加到您的表格

INDEX(id, timestamp)

并使用

WHERE id = :id
ORDER BY timestamp DESC
LIMIT 10

任何索引都按索引排序。这就是你要找的10行彼此相邻。即使数据被推出缓存,也可能只有一个块来提供这10行。

但InnoDB中的二级索引中的“行”不包含满足SELECT *的数据。索引“row”包含指向实际“数据”行的指针。因此,将有10次查找来获取它们。

至于观看次数,让我们以不同的方式实现:

CREATE TABLE ViewCounts (
    post_id ...,
    ct MEDIUMINT UNSIGNED NOT NULL,
    PRIMARY KEY post_id
) ENGINE=InnoDB;

现在,给定post_id,深入挖掘BTree以查找计数非常有效。 JOINing这个表到另一个,我们用另外10个查找得到个别计数。

所以,你说,“为什么不把它们放在同一张桌子上”?原因是ViewCounts变化如此频繁,以至于这些行为将与其他活动发生冲突。最好将它们分开。

即使我们打了几十个街区,但与扫描数百万行相比,这还不错。而且,这种数据有点“可缓存”。最近发布的帖子更频繁。热门用户访问频率更高。因此,100GB的数据可以充分缓存在10GB的RAM中。缩放就是“计算磁盘命中率”。