2500 亿行 - 大规模计算互连性

tho*_*123 4 schema performance database-design optimization

我有一个大约 700k 行的表,每行都由一个唯一的 itemnumber 标识。

通过计算指示关联强度的单个数值或两个项目之间的数学“距离”,每行/项目可以与表中的任何其他行/项目相关联,没有关联/无限距离由“0”表示" 而数值“1”表示相同项目/无距离。

这些关联编号难以计算/计算密集并且基于存储在单独数据库中的数据。因此,为所有行组合预先计算一次,然后只为添加的新行(每年 <4k 新行)预先计算它们似乎是有道理的。

生成的关联表可能如下所示:

itemnumber    |  associatedwithitem        | associationstrength

23920390293   |   12356456885              | 0.12255888644888

45468411516   |   44565464884              | 0.91155684161123

45648855222   |   98956221818              | 0.00000000000000

45468411516   |   23920390293              | 0.46813185844468
Run Code Online (Sandbox Code Playgroud)

然而,这样一个表的大小将是巨大的:((700,000 x 700,000) - 700,000)/2 = 244.999.650.000 = 大约 2500 亿行,即使在丢弃所有自连接(公式中的 -700,000)并存储之后每个连接只有一种方式(公式中除以二)。

我将只运行一种类型的查询,如下所示:

“给定一个 itemnumber 列表(见上表示例),计算平均(mean)关联数。”

针对关联表运行的每个 itemnumber 列表通常包含 < 1k itemnumber,但很少会大到 50k。但是因为 1k 个 itemnumber 的列表中的每个数字都将与 700k 个其他 itemnumber 相关联,这样的查询将提取 700,000 x 1000 = 700,000,000 个关联号,然后需要计算这 700m 个关联号的平均值。

对以下方面的任何想法:

  1. 保存此表的最佳数据管理系统
  2. 结构(2500 亿行 vs 700k 行,每个行包含关联数据的 blob)
  3. 提取数据和计算均值的最佳方法

任何输入都会有所帮助。

Kev*_*sel 6

简短的回答:这取决于。

长答案:答案取决于几个因素。以下是一些:

  1. 您的 700K 行表是否很少更新?如果是这样,我会倾向于预先计算手段。如果它们不是静态的,而是以规律的、可预测的时间间隔(例如,每月或每年)变化,那么预先计算可能仍然是一个可靠的答案。如果它们经常或不可预测地变化,则预先计算变得更难证明。您确实提到每年添加的行数与总数相比相对较少。
  2. 现有的项目编号是否会发生变化?如果不是,这是有利于预先计算的一个因素。如果它们确实发生了变化,则根据变化的频率,预先计算变得有点难以证明其合理性。
  3. 你有可用的磁盘空间吗?假设您有 250,000,000,000 行。您的关联表将有两个 bigint(每个 8 个字节)和一个十进制(8,7)(每个 5 个字节),或每行 23 个字节。对于 2500 亿行@每行 23 个字节,您看到的容量超过 5 TB。您需要考虑事务日志的磁盘空间、数据库备份、可能具有开发/QA/登台环境、(可能)在表上具有非聚集索引等。根据您的数据库产品,您可以进行压缩减少相当大的数量,但我想说在实现之前你可能需要至少 15-25 TB 的可用磁盘空间;如果您无法获得那么多磁盘空间,那么实现这种关系是行不通的。
  4. 这个过程对时间有多敏感?我不知道当您将其作为脚本的一部分进行计算时,常规运行需要多长时间,但是如果这些作业可以在后台或夜间运行,那么这将是预先计算的一个因素。即使您进行了预先计算,您也可能会扫描 2500 亿行表来获得答案,因此在任何一种情况下性能都不会很出色。
  5. 这些请求多久出现一次?如果是一个月一次,那就反对预先计算。但是,如果请求每天(或同时出现多个),预先计算可能是更好的选择。
  6. 这个服务器还有什么用?如果从积极的机器运行这个,你可能希望预先计算和大表中选择。原因是扫描 5 TB 数据会导致几乎所有其他内容耗尽内存,从而损害其他所有内容的性能。另一方面,如果这是一个研究服务器、开发服务器,或者您不介意在运行这些查询后服务器的性能下降,那么预计算就没什么大不了的。
  7. 请求中项目重复的频率是多少?换句话说,项目 23920390293(例如)是否出现在很多报告中,或者单独的请求本质上是不同的?如果您看到了共同的元素,那么就支持预计算(因为那样您只需要计算一次),但是如果请求很少重复数字,则您不会从预计算中获得太多收益。

如果您确实将其保存在 SQL 表中,我建议您不要使用 blob。我认为与压缩表相比,您不会获得太多(如果有的话)大小增加,并且您可能会受到性能影响。即使您使用单独的服务器来执行应用程序级计算(而不是在数据库中进行),我认为保持表规范化仍然有意义。

此外,如果您拥有世界上所有的磁盘空间,您可能希望保留两侧(A 和 B 之间的距离,以及 B 和 A 之间的距离)。您将所需的磁盘空间量增加了一倍,但使查询变得简单得多:您的项目列表和主项目关系表之间的一个连接,而不是两个单独的查询(以及确保您拥有之间的所有关系的额外困难表)。