【问题标题】:Appropriate database design for sparse user profiles针对稀疏用户配置文件的适当数据库设计
【发布时间】:2016-10-29 16:48:18
【问题描述】:

我想有效地存储和查询用户数据。用户由唯一的 UUID 标识,并且可以具有数百个不同属性的值(所有布尔值、数字或字符串)。但是,对于大多数用户而言,已知属性的数量非常有限,因此大多数值为空。此外,一些属性本质上是分层的(例如,女性(是-否)-> likes_heels(是-否)-> likes_red_heels(是-否))。有 1 亿不同的用户,并且经常添加新的可能属性。

我正在考虑 3 个选项:关系表结构(例如 Impala)、键值存储(例如 HBase)和基于 JSON 的数据库(例如 MongoDB)。

目前的重点是执行查询(例如,有多少用户是男性、30 岁以上和中国人?)

期待您的推荐!

【问题讨论】:

    标签: mongodb database-design hbase impala database


    【解决方案1】:

    我可以分享我对类似用例的经验。我们使用 HBase 来存储数以千计的此类属性。请注意,在我们的例子中,属性值总是 true/false/null。 Null 意味着我们无法果断地判断它是真是假。

    目标是

    • 为复杂的布尔表达式运行大规模聚合。例如,给我所有女性用户以及在 2 个日期之间喜欢高跟鞋的用户的聚合(计数)。
    • 允许在样本的聚合之上运行,因为在大多数情况下,样本向我们提供了趋势的公平指示(非常快速)
    • 能够添加属性
    • 最大限度地减少存储空间,从而减少扫描时间

    我们将所有属性编码为位图数据结构。每个属性都有一个唯一的偏移值(位图中的位置)。如果设置了位,则用户是女性或喜欢高跟鞋。为了处理 null,我们为每个用户存储了一个额外的位图。如果第一个位图中的某个位为假,那么我们检查第二个位图中的相同位置以查看它是否为真。如果第二个位图设置了位,我们将其视为 null。

    BitMap 本身将占用空间减少了一个数量级。您还可以使用像 Roaring Bit Maps 这样的稀疏位图结构来减少存储并提高效率。

    在位图(字节数组)中查找位是一个常数时间操作。然后我们使用 HBase 协处理器来执行聚合。客户端将传递布尔表达式,如

    att1 && att2 && (att3 || att4)
    

    客户端还将传递表达式中每个属性的偏移量。这使协处理器能够根据偏移量扫描位以查找已过滤的行。

    我们的行键设计基于用户 ID 的 SHA1。是

    <FIRST 2 BYTES of SHA1><DD-MM-YYYY><40 bytes of SHA1>
    

    这允许我们使用 HBase 的模糊行过滤器来

    • 从可能的 256 个分片(前 2 个字节)中扫描一个样本
    • 扫描日期范围

    我已经为大约 6000 个没有稀疏位图的属性和大约 15000 个带有稀疏位图的属性测试了这种方法。在某些情况下,可以在位图中对数字属性进行建模(显然不是连续值)。

    我们希望处理 4-50 亿用户,并且每个用户被建模大约 3 次(平均),因此存储了大约 150 亿个此类事件(用户 ID - 日期 - 建模属性集)。我们还支持执行不同计数的功能,因为同一用户在不同日期可能具有不同建模的属性。

    我们在 Map/Reduce 中执行了所有编码,并使用 HBase 批量加载功能来执行极快的加载。

    这种设计的优点之一是,由于我们在 HDFS 中保存了所有编码数据的副本,因此我们可以编写自定义 Hive/Impala/Spark UDF 来执行过滤/评估,以便通过 SQL 进行查询。此外,HDFS 中的副本作为冷层可以保存更长时间(比在 HBase 中保存的时间更长)。

    我们也考虑过 Apache Phoenix,但我们没有选择它,因为我们希望支持同时聚合 100 个表达式而不是一次一个表达式。

    我希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-04
      • 2013-11-14
      • 2018-07-24
      • 2020-12-01
      • 2012-04-29
      相关资源
      最近更新 更多