数据库结构的最佳实践,以跟踪用户是否打开了某个内容?

时间:2014-11-02 16:28:40

标签: php mysql database user-tracking

目前我建立了一个网站,其中包含许多有效和无效的内容。发布内容时,它处于活动状态,一段时间后变为非活动状态。我想跟踪在活动期间打开内容的所有用户。将这些信息存储在数据库中的最佳方法是什么?

我需要在以下问题下查询数据库: 1.哪些用户打开了特定内容?对于每个内容,管理员可以轻微地查询,也许两到三次。 2.特定用户打开了哪些活动内容? 3.特定用户打开了哪些非活动内容(内容,在打开时处于活动状态并且在此期间处于非活动状态)?两个查询的查询频率都高于第一个查询(可能每两周或三周)。用户可以查看他/她的个人资料,他/她打开了哪些内容。

首先,我想到了一个包含三列的数据库表:"用户ID","内容ID","状态"。在哪里"状态"对于活动内容为true,对于非活动内容为false。 "用户ID"和"内容ID"是主键和"状态"是内容表中的外键。但后来我想到了这张桌子的大小。在某些年份(希望)可能有200万个节点和25万用户,因此可能有500亿行...我认为,这将大大降低性能。

因此我想到了另一种方式:我创建了两个数据库表,一个叫做" content_opened_by_users"另一个名为" user_opened_content"。前者将包含两个列:"内容id"和"用户"。用户"用户"是包含所有用户ID的序列化数组,它在同一行中打开相应的内容ID。第二个表格将包含三列:"用户ID","有效内容","无效内容"。其中"活跃内容"和"非活动内容"也是序列化数组,包含相应用户打开的活动/非活动内容的内容ID。 因此,无论何时用户打开内容,服务器都会从" content_opened_by_users"内容中加载相应的"用户" -array。表和相应的"活动内容" -array来自" user_opened_content"表。如果" users" -array中尚未存在用户ID,则会添加该用户ID,如果内容ID尚未存在于"活动内容" -array中,则也加入。然后两个数组都将被覆盖在数据库中。 现在,如果我查询所有用户打开了某个内容,我会从" content_opened_by_users"中获取一个数组。表。如果我查询由特定用户打开的所有活动/非活动节点,我会得到"活动内容"和"非活动内容"来自" user_opened_content"的数组表。然后我检查,如果"活动内容" array包含一些内容id,它们同时处于非活动状态并将它们传输到"非活动内容"数组并将它们传递回数据库。

我知道,我在这两个表中创建了冗余数据,但我希望这会提高性能。

那么,这是一种实现用户跟踪的便捷方式吗?或者可能有另一种更有效的方式吗?

我欢迎任何建议! 非常感谢你。 丹尼尔

1 个答案:

答案 0 :(得分:0)

首先,您可能需要阅读database normalization

为了跟踪您描述的信息,我会为用户,内容和访问使用单独的表格,如下所示:

table    | columns
-------------------
users    | id, login, ...
content  | id, title, active, ...
access   | id, user_id, content_id, timestamp, ...

然后,无论谁打开哪个项目,您都可以存储用户和内容项目。 access表包含有关哪个用户在哪个时间打开哪个内容项的条目。这使您可以跟踪大量统计信息,而无需存储有关用户而不是打开项目的任何信息。

主要查询是:

  1. 哪些用户打开了一个项目

    SELECT DISTINCT users.login FROM access JOIN users ON access.user_id = users.id JOIN content ON access.content_id = content.id WHERE content.title LIKE '%test%'
    
  2. 用户打开的有效内容

    SELECT DISTINCT content.title FROM access JOIN users ON access.user_id = users.id JOIN content ON access.content_id = content.id WHERE content.active = true AND user.login = 'testuser'
    
  3. 用户打开的非活动内容

    SELECT DISTINCT content.title FROM access JOIN users ON access.user_id = users.id JOIN content ON access.content_id = content.id WHERE content.active = false AND user.login = 'testuser'
    

    假设访问只能发生在活动内容上。要跟踪状态更改的时间,请添加另一个表,您可以使用该表查找上次更改的时间戳并与访问条目进行比较。

  4. 请注意,这些查询根本没有优化。您还应添加相应的FOREIGN KEY constraints以确保数据一致性,并考虑添加其他索引以提高性能。