2

我有一个博客程序(类似于 Twitter),我目前正在制作一个最近访问过的框,其中包含最近访问过您页面的 9 个人。

每个人都使用不同的用户名注册。

我目前拥有的是这样的数据库:

-----------------------------
| id | username | who_visit |
-----------------------------

例如,如果有 9 个用户foo1访问foo9foo10的页面,则数据库将填充一行:

------------------------------------------------------------------------
| id | username |                       who_visit                      |
------------------------------------------------------------------------
| 1  |  foo10   | foo1, foo2, foo3, foo4, foo5, foo6, foo7, foo8, foo9 |
------------------------------------------------------------------------

然后当foo11访问foo10的页面时,我会foo9从字符串的末尾删除,并添加foo11到前面。

但是现在的主要问题是,如果foo1访问过foo10的页面,然后foo2访问过foo10的页面,然后再次foo1访问过foo10的页面怎么办?然后我必须搜索 9 个用户,删除所有重复项,将这个放在前面,然后继续执行。但问题是,它只会显示 8 行。

我能想到的解决这个问题的唯一方法是制作一个这样的数据库:

-----------------------------
| id | username | who_visit |
-----------------------------

而不是将它们填充在一行中,我会为每次访问添加一个新行:

-----------------------------
| id | username | who_visit |
-----------------------------
| 1  |  foo10   |    foo1   |
-----------------------------
| 2  |  foo10   |    foo2   |
-----------------------------
| 3  |  foo10   |    foo3   |
-----------------------------
| 4  |  foo10   |    foo4   |
-----------------------------
| 5  |  foo10   |    foo5   |
-----------------------------
| 6  |  foo10   |    foo6   |
-----------------------------
| 7  |  foo10   |    foo7   |
-----------------------------
| 8  |  foo10   |    foo8   |
-----------------------------
| 9  |  foo10   |    foo9   |
-----------------------------

但这会占用大量不必要的空间。

有没有我错过的方法,它可以有效地解决这个问题,而无需为数据库中的一个用户添加 > 50000 行?

更新:对于那些有同样问题的人,正如下面评论中的 PM 77-1 所述,可以在插入新行时删除最早的重复行。这样,您就不会得到“数据膨胀”。

4

5 回答 5

2

你的第二种方法是最好的。当我第一次开始在我的应用程序中实现数据库时,我尝试了你的第一种方法。当您想要扩展或更改数据集的处理方式时,它会产生问题。

如果索引正确,您应该可以快速排序这些数据。

您仍想从 whovisit 表中删除最旧的行。这将阻止您的 50k 条目。理论上,每个用户的 whovisit 表中只保留 9 条记录。所以你的实际表大小是 9*Number_of_users

表一用户

id   |  username
-----|-----------
1    |  foo1
2    |  foo2

表二 whovisit

id   |  user(id) | visited(userId) | Date/time stamp
-----|-----------------------------|----------------
1    |  1        |  2              | 9999-12-31 23:59:59

当您插入新访问的查询时,用户 id 并获得行数。如果小于 9 则罚款,如果大于 9,则删除最旧的一个,总共为用户留下 9 行。

于 2013-03-10T00:27:22.187 回答
2

添加每次访问的日期/时间戳似乎会有所帮助。

如果你这样做,逻辑可能是这样的:

  • 用户已经在列表中 - 用当前日期/时间更新最早的时间/戳
  • 用户尚未在列表中 - 查找总体最早访问并使用此用户的信息更新记录
于 2013-03-10T00:35:18.570 回答
0

我建议使用两个表:

桌子users

id | name
1  | foo1
2  | foo2
3  | foo3
4  | foo4   
  ...
10 | foo10

桌子visits

host_userid | visitor_userid
    10      |     1
    10      |     2
    10      |     3
    10      |     4

如有必要,该visits表还可能具有日期列或主键。仅存储两个整数将导致非常小的行大小。

于 2013-03-10T00:33:31.863 回答
0

你的想法被称为规范化,实际上是一个好主意。

用户

-----------------
| id | name     |
-----------------
| 1  | foo1     |
-----------------
| 2  | foo2     |
-----------------
| 3  | foo3     |
-----------------

餐桌参观

-----------------------------
| id | user_id  | visit_id  |
-----------------------------
| 1  |    1     |    2      |
-----------------------------
| 2  |    2     |    3      |
-----------------------------

现在您可以轻松快速地存储和检索访问数据。如果你把它放在一个领域(就像你的第一个例子),你最终会陷入程序员的地狱。

您可以在表访问中包含时间戳并删除早于 x 天的条目。

于 2013-03-10T00:35:48.423 回答
0

改用关系表...由于显而易见的原因,不建议在您的用户表中创建多个 ID...

例如:

Users桌子

[ UserID] [UserName]

Visits桌子

[ Source_User_ID][ Visitor_User_ID][ Visit_Count]

然后,您的 SQL 语句变得非常简单:

SELECT TOP 9 [Visitor_User_ID] WHERE [Source_User_ID]=### ORDER BY [Visit_Count] DESC
于 2013-03-10T00:36:09.040 回答