2013-03-10 73 views
3

我有一个博客程序(类似Twitter),我目前正在制作一个最近访问的框,其中包含最近访问过您的页面的9个人。什么是存储和显示最近访问他人页面的人最有效的数据库方式?

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

什么我目前得到的是这样的数据库:

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

例如,如果9个用户foo1foo9访问foo10的页面,该数据库将与行填充

------------------------------------------------------------------------ 
| 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,可以在插入新行时删除最早的重复行。这样,你不会得到'数据膨胀'。

+1

如何分割的逻辑:如果访问者已经在列表上,则代替他/她最早 – 2013-03-10 00:29:51

+0

@ PM77-1哎,为什么我没有想到这一点。 – think123 2013-03-10 00:30:44

+0

我将它扩展为答案。 – 2013-03-10 00:37:08

回答

3

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

如果索引正确,您应该没有问题通过快速排序这些数据。

您仍想从whovisit表中删除最旧的行。这会阻止你的5万个条目。理论上,每个用户的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行。

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表还可能有一个日期列或者一个主键,如果需要的话。仅存储两个整数将导致非常小的行大小。

+0

但仍有许多行使用。 – think123 2013-03-10 00:33:56

+0

@ think123:是的,但所需的存储空间量并不直接取决于行数,而是取决于'number_of_rows * row_size'。在你的第一个例子中,你有更少的行,但行大小更大。 – Hazzit 2013-03-10 00:36:05

2

看来这将有助于添加每次访问的日期/时间戳。

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

  • 用户已经在名单上 - 更新与当前日期最早的时间/时间戳/时间
  • 用户还没有在名单上 - 找到总体最早的访问,并与该用户的信息更新记录
+0

我同意。谢谢! – think123 2013-03-10 00:57:25

+0

使用时间戳+1 – 2013-03-10 01:39:09

0

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

用户

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

访问

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

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

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

0

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

例如:

Users

[UserID] [UserName]

Visits

[Source_User_ID] [Visitor_User_ID] [Visit_Count]

然后你的SQL语句BEC青梅多用简单:

SELECT TOP 9 [Visitor_User_ID] WHERE [Source_User_ID]=### ORDER BY [Visit_Count] DESC 
相关问题