优化SQL以确定每个用户的唯一页面查看

时间:2010-08-28 12:12:38

标签: sql database-design optimization postgresql doctrine

我需要确定用户是否已访问过某个网页,以便跟踪唯一的网页浏览量。

我已经实现了一些HTTP头缓存,但现在我需要优化SQL查询。

在以下情况下,访问是独一无二的:

  • 对:page_id + user_id位于visit
  • 或配对:找到page_id + session_id
  • 或:page_id + [ip + useragent] - (这是另一个讨论的主题,是否只应该是ip或ip + useragent)

所以我有一个跟踪用户访问的表格:

visit:
    page_id
    user_id
    session_id
    useragent
    ip
    created_at
    updated_at

现在每次访问用户(没有点击缓存)我会更新一行(如果存在)。如果有任何受影响的行,我将在表中插入新访问。

这是一个或两个查询(假设缓存可以工作,主要是两个查询),但行数以某种方式受到限制。也许最好存储所有访问,然后在例如清理数据库中清理数据库。一个月?

问题是:

  • 应该如何构造visit表(键,索引,与userpage_views表的关系)。一些重要的字段可能为null(例如user_id),那么索引呢?我需要多列主键吗?
  • 哪个是查找唯一用户最快的SQL查询?
  • 这是一种理智的方法吗?

我使用PostgreSQL和PDO(Doctrine ORM)。 我的所有会话都存储在同一个数据库中。

2 个答案:

答案 0 :(得分:2)

我个人不会把它放在请求 - 响应路径中。我会将原始数据记录在表中(或将其推送到队列中)并让后台任务/线程/ cron作业处理。

队列(或消息传递表)应该只包含pageid,userip,sessionid,useragen,ip。

只要后台任务能够跟上,绝对时间就不那么重要了。由于单个线程现在将执行繁重的工作,因此在更新唯一的网页浏览表时不会产生冲突的锁。

答案 1 :(得分:0)

只是一些随意的想法:

我可以验证独特访问类型背后的想法是:

  1. pageid + userid = user已登录
  2. pageid + sessionid =用户未识别但已启用Cookie
  3. pageid + ip / useragent =用户未识别且未启用Cookie
  4. 对于原始性能,您可能认为#2是冗余的,因为#3 可能覆盖#2 i大多数条件(或者#2重要,例如,如果用户然后注册然后#2可以被映射到#1)? (意味着会话ID可能仍会被记录,但不会在任何访问确定中使用)

    IMHO IP将始终存在(即使是欺骗性的)并且将成为索引的良好候选者。用户代理可以隐藏,只有有限的范围(不是很容易选择)。

    由于可空字段,我会在此实例中使用代理主键,因为没有字段本身是唯一的。

    恕我直言,你的想法是存储所有访问,然后通过批量删除修剪重复是一个很好的权衡(而不是检查是否存在更新与插入新)

    • 所以PK =代理人
    • 群集=不确定 - 另一个查询/要求可能会更好地推动这一点。
    • NonClustered Index = IP地址,页面ID(假设IP地址多于页面ID)