代码之家  ›  专栏  ›  技术社区  ›  takeshin

优化SQL以确定每个用户的唯一页面视图

  •  4
  • takeshin  · 技术社区  · 15 年前

    我需要确定用户是否已经访问过一个页面,以便跟踪唯一的页面视图。

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

    访问是独一无二的,当:

    • 一对: page_id + user_id 发现在 visit 桌子
    • 或配对: 帕吉罗伊德 + session_id 被发现
    • 或: 帕吉罗伊德 + ip + useragent ]-(这是另一个讨论的主题,无论它应该是IP还是IP+用户代理)

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

    visit:
        page_id
        user_id
        session_id
        useragent
        ip
        created_at
        updated_at
    

    现在,在每次用户访问(不命中缓存)时,如果行存在,我将更新它。如果有任何受影响的行,我将向表插入新的访问。

    这是一个或两个查询(假设缓存可以工作,大多数是两个查询),但是行的数量在某种程度上是有限的。也许最好是储存起来 全部的 访问,然后在一个月内清理数据库?

    问题是:

    • 应该怎么做 参观 构造的表(键、索引、与的关系 user page_views 表)。一些重要字段可能为空(例如,用户ID),那么索引呢?我需要多列主键吗?
    • 哪一个查询是找到唯一用户最快的SQL查询?
    • 这是明智的做法吗?

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

    2 回复  |  直到 15 年前
        1
  •  2
  •   Peter Tillemans    15 年前

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

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

    只要后台任务能跟上,绝对时间就不那么重要了。由于现在单个线程将执行繁重的提升操作,因此在更新唯一的页面视图表时,它不会创建冲突的锁。

        2
  •  0
  •   StuartLC    15 年前

    只是一些随机的想法:

    我能证明独特的拜访类型背后的想法是:

    1. pageid+userid=用户已登录
    2. pageid+sessionid=未识别用户,但已启用cookie
    3. pageid+ip/useragent=未标识用户且未启用cookie

    对于原始性能,您可能认为2是冗余的,因为3将 可能 cover 2 i大多数情况(或是2重要,例如,如果用户随后注册,然后2可以映射到1)?(意味着会话ID可能仍然被记录,但不会用于任何访问确定)

    imho ip将始终存在(即使是欺骗的),并且将是索引的一个很好的候选者。用户代理可以隐藏,并且只有有限的范围(不是非常可选)。

    由于可以为空的字段,并且这些字段本身都不是唯一的,所以在这个实例中我将使用代理主键。

    imho您关于存储所有访问,然后通过成批输出来修剪重复项的想法是一个很好的权衡方法(而不是检查是否存在以更新或插入新的访问)。

    • 所以pk=代理
    • 集群=不确定-另一个查询/需求可能会更好地推动这一点。
    • 非聚集索引=IP地址,页ID(假定IP地址比页ID更独特)