【问题标题】:Database design, how many times user visit specific page in application数据库设计,用户在应用程序中访问特定页面的次数
【发布时间】:2013-10-30 16:10:52
【问题描述】:

Web 应用程序将为用户提供来自不同类别的不同帖子。
例如类别可能是“幽默”、“运动”等。

所以为此我将有 简单的表: Categories(id, category_name).

我想跟踪用户访问特定类别的次数,因此下次用户登录时,他的默认页面将是用户访问次数最多的两个不同类别的帖子的页面。

对此的基本想法(我将使用 Ruby on Rails),在控制器提供某个页面之前,该类别的计数器将递增并保存到数据库中。 我的问题是我不知道在哪里保存这个类别的计数器?

第一个想法(表计数器):

Counters(id, category_name1, category_name2, ..., category_nameN, user_id)

其中 category_name 是整数字段,表示用户访问次数(特定类别)。 这个想法不好,因为当我添加新类别时,我必须更改此表以添加新列。

第二个想法:

Counters(id, count, category_id, user_id)

对我来说更好的主意但我猜仍然不是很好的性能,因为每个 ONE 用户我将有 N 行,其中 N 是类别数。那么如果我有 1000 个用户和 10 个类别会被过度杀戮?

【问题讨论】:

  • 我看不出你的第二个想法有什么问题(除非我们谈论的是非常大的系统)。最后,计数器是分配给每对用户和类别的属性。事实上, (user-id, category_id) 是您关系中的一个键,因此您可以省略 id 列。该键将使用唯一索引实现,因此您的应用程序将有一个非常快速的访问您的计数器的路径。根据您的 DBMS,您可能还决定优化物理参数,例如使用索引组织表(它将仅在索引数据中存储索引和计数器)。

标签: ruby-on-rails database database-design user-preferences


【解决方案1】:

使用第二种方法。 1000 个用户 * 10 个类别 = 10000 行,这在数据库世界中绝不被视为“大”。

除非你的客户端库强迫你,否则你应该使用natural key设计:

Counter(user_id, category_id, count, PRIMARY KEY (user_id, category_id))

如果您的 DBMS 支持clustering,则整个表在物理上可以表示为单个 B-Tree,这样可以高效地查询、修改和缓存。

话虽如此,你确定你需要永恒的计数吗?也许只保留最近 30 天的计数会更好1?这需要:1000 个用户 * 10 个类别 * 30 天 = 300000 行,这仍然不是特别“大”。

或者,您可以运行定期批处理作业,将所有计数乘以小于 1 的某个因子(例如 0.9),这会使旧访问不如新访问“重要”。在这种情况下,您可能希望对计数器使用某种浮点类型(而不是整数)。


1 或 90 或其他...

【讨论】:

    【解决方案2】:

    对于该卷,我将使用第二种方法 -

    Counters(id, count, category_id, user_id)
    

    除非您遇到性能问题,然后才切换到其他方法。

    您还可以使用计数器缓存来帮助解决此问题:

    http://guides.rubyonrails.org/association_basics.html#detailed-association-reference

    例如

    class Counter < ActiveRecord::Base
      belongs_to :category, dependent: :destroy,
        counter_cache: true
    end
    

    与 Rails 一样,最好先从 Rails 开始,然后再离开。

    【讨论】:

      猜你喜欢
      • 2011-06-09
      • 2017-02-24
      • 1970-01-01
      • 1970-01-01
      • 2017-12-23
      • 2010-12-01
      • 1970-01-01
      • 2015-04-05
      • 2011-10-22
      相关资源
      最近更新 更多