【发布时间】:2014-09-09 15:06:59
【问题描述】:
假设您有一个包含 10 个 Mio 记录的表“用户”和一个包含 1 个 Mio 记录的表“组”。平均而言,每个组有 50 个用户,我至少将它们存储在一个名为 users2groups 的表中的 rdbms 中。 users2groups 实际上是一个稀疏矩阵。只有 80% 的用户和组完整数据集适合可用内存。组成员 (users2groups) 的数据位于顶部,因此如果需要内存来缓存组成员,则必须从用户表或组表或两者中释放内存。
我希望能够:
- 按名称快速查找用户并
- 按名称快速查找组和
- 快速获取组中的所有用户并且
- 快速获取用户所属的所有组
根据我的经验,磁盘延迟在很大程度上决定了您的访问速度。您还可以在读取和写入速度之间取得平衡。然而,在这之前,必须先决定一种数据库类型……例如:
- 关系型 DBMS
- 键值对存储
- 文档存储
- RDF 商店
- 面向对象的 DBMS
- 图形数据库管理系统
- 搜索引擎
- 多值 DBMS
- 本机 XML DBMS
- 宽列存储
- 内容商店
- 导航 DBMS
- (压缩)位图
- 文件
- 更多...?
所以问题是,当 RAM 容量低于考虑稀疏矩阵的可用数据时,所有这些系统中的哪一个或哪些组合可提供最佳的整体读取访问性能(具有可接受的写入访问性能)? ...以及如何在所选技术中平衡所有三个实体/表的内存利用率...?
由于这是一个概念性问题,磁盘空间和 CPU 容量超出范围或被视为“无限期”可用。
顺便说一句。我知道,通过使用基于哈希的索引(例如 crc32(lower(STRING))),可以有效地加快搜索用户名或组名等名称的速度 - 一个示例 select 会比这样:select somethinguseful from name=SEARCHSTRING 和 hash=crc32(lower(SEARCHSTRING)) 的用户。然而,当我说用户和组表有 80% 的 RAM 覆盖率时,哈希和它们的索引还没有包含在内存中。那是因为我不清楚,如果没有更好的集成解决方案。目前我只是假设,将整个主题分成用户、组和用户组三个部分是最明智的。我这里缺乏证据。
-------- 更新 -------------- ------------
我了解桌面上存在相互竞争的概念:
- 对非规范化进行了扩展,在这种情况下,我可以处理非常少的磁盘查询集。 (例如 mongodb 等)
- 压缩数据以使大部分数据无论如何都适合内存(例如压缩位图)
由于非规范化意味着:“增加数据量”,这两个概念似乎相互矛盾。是否有最佳实践或科学或明智的论据,何时使用非规范化以及何时使用挤压数据方法?例如。一个 KPI 说:如果小于 80% 适合内存,就去非规范化吧?
-------- 更新 -------------- ------------
额外的内存需要额外的钱,大多数数据库服务器通常都有很多空磁盘空间,让他们感到厌烦。所以非规范化很便宜。另一方面,非规范化机会是有限的:磁盘延迟在物理上限制了每秒最大查询量,句号。太多对磁盘的查询被排队,这将非规范化限制为具有大量流量的应用程序的扩展。即使是非规范化的数据访问速度也很大程度上取决于内存。
所以也许 KPI 在这里是不可能的。无论如何,对于给定的稀疏矩阵示例,非规范化和压缩数据方法需要如何平衡?我想在压缩用户和组表时,将它们留在 rdbms 中,然后将释放的内存分配给服务于 users2groups 关系的文档数据库的缓存。然而,这引入了一系列新问题,例如处理 2 个数据库系统的多次往返和更复杂的查询管理。那么如何解决呢?
----------- 更新 -----
根据 lagivan 的建议,只有标记关系的稀疏矩阵似乎以一种明智的方式解决:有 2 个表用户和组,然后在表用户中有一个多重 ID 字段,其 ID 与组相关,反之亦然在表中分组多个 ID 字段,其中包含与用户相关的字段。我猜这个解决方案并没有与特定技术紧密耦合。它甚至可以通过 VARBINARY 或任何 blob 在 MYSQL 中实现。
问题的突出部分与包含一些“果汁信息”如状态或 lastupdatedate 的稀疏矩阵有关。因此,使用外键数组会按概念禁用这些信息。因此,这种情况的原始问题仍然悬而未决:当 RAM 容量低于考虑稀疏矩阵的可用数据时,所有这些系统中的哪一个或哪些组合提供最佳的整体读取访问性能(具有可接受的写入访问性能)? ...以及如何在所选技术中平衡所有三个实体/表的内存利用率...?
【问题讨论】:
-
你能澄清一下 status/lastupdatedate 吗?它与users2groups关系有关吗?所以你想存储用户被添加到组的日期,对吧?
-
确切地说:lastupdatedate 是关于用户被添加到组的时间。状态可以是数值或 ID,例如。 0 表示“已删除”,1 表示“活动”,2 表示“提议”,3 表示“待确认”。不是针对给定的示例,但通常在稀疏矩阵中可能还需要存储特定的数值或阈值或目标日期。用 RDBMS 术语来说,我会说交叉引用获得了额外的字段。
-
这些附加要求对设计至关重要。我建议你先写下最常见的用例。设计应该基于这些用例,以便为它们提供最佳性能。例如,问题是您何时想要获取这些日期和状态 - 将它们显示在用户屏幕上还是显示在组屏幕上?它会影响您存储它们的最佳方式。
-
我不明白这一点。让我们考虑三个字段:1. createddate,2. lastupdateddate,3. Status-ID,如另一条评论所示。在 RDBMS 中,您只需将它们附加到 users2groups 表,然后将它们用于不同的事情 - 例如:仅显示组的活动用户。根据创建时间和用户数量绘制用户增长路径。根据 lastupdateddate 和 status=deleted 绘制一个fluction路径。绘制一组或一组组的波动图。显示最近推荐的前 20 名用户。通常随着时间的推移需求增加......
-
查看我的更新答案。
标签: bitmap rdbms database-performance graph-databases key-value-store