一种更有效的方法来总结 postgres 中列之间的差异?

Posted

技术标签:

【中文标题】一种更有效的方法来总结 postgres 中列之间的差异?【英文标题】:A more efficient way to sum the difference between columns in postgres? 【发布时间】:2019-09-19 15:29:23 【问题描述】:

对于我的应用程序,我有一个包含这三列的表:user, item, value

以下是一些示例数据:

user    item    value
---------------------
1       1       50
1       2       45
1       23      35
2       1       88
2       23      44
3       2       12
3       1       27
3       5       76
3       23      44

我需要做的是,对于给定的用户,针对其他所有人的值执行简单的算术运算。

假设我想将用户 1 与其他所有人进行比较。计算如下所示:

first_user    second_user    result
1             2              SUM(ABS(50-88) + ABS(35-44))
1             3              SUM(ABS(50-27) + ABS(45-12) + ABS(35-44))

这是目前我程序中的瓶颈。例如,我的许多查询开始需要 500 多毫秒,而这个算法大约需要 95% 的时间。

我的数据库中有很多行,它是 O(n^2)(它必须将所有用户 1 的值与其他所有人的匹配值进行比较)

对于如何提高效率,我相信只有两种选择。首先,我可以缓存结果。但是由于需要 NxN 空间,生成的表会很大,并且值需要相对新鲜。

第二种方法是使算法更快。我搜索了“postgres SIMD”,因为我认为 SIMD 听起来是优化它的完美解决方案。我找到了几个相关链接,例如 this 和 this,但我不确定它们是否适用于此。此外,它们似乎都有 5 年左右的历史并且相对无人维护。

Postgres 是否支持这种功能?您可以在哪里“矢量化”一列,或者可能导入或启用某些扩展或功能,以允许您对多行快速执行这些类型的基本算术运算?

【问题讨论】:

覆盖索引可以提高性能,如果你还没有的话。在您展示的简化示例中,这可能采用以下形式:create index ix1 on my_table (user, item, value) @TheImpaler 在查找之前我从未听说过覆盖索引,谢谢。 现在,如果“需要比较新鲜的值”,您还可以使用将计算值存储在表上的策略,并定期刷新它们。如果一天有 24 小时,则每小时可以刷新 1/24 的用户;每个用户数据将最多 23 小时“陈旧”。一个 cron 工作就可以解决问题。 围绕矢量化执行进行了一些讨论,但到目前为止,还没有任何内容导致核心中的具体实现。您是否尝试为这些查询启用 JITting? @a_horse_with_no_name 我以前也从未听说过。现在试一试,但不确定我是否做得正确。我跑了set JIT = true; 然后SET jit_above_cost = 10;SET jit_inline_above_cost = 10;SET jit_optimize_above_cost = 10; 但查询似乎仍然需要相同的时间。 【参考方案1】:

我不确定你从哪里得到 O(n^2)。您需要查找用户 1 的行,然后为其他所有人读取数据。假设项目少而用户多,这基本上是 O(n),其中“n”是表中的行数。

查询可以表述为:

select t1.user, t.user, sum(abs(t.value - t1.value))
from t left join
     t t1
     on t1.item = t.item and
        t1.user <> t.user and
        t1.user = 1
group by t1.user, t.user;

对于此查询,您需要在t(item, user, value) 上建立索引。

【讨论】:

嗯,有很多项目和很多用户。我已经在做类似的事情,这是我的瓶颈和性能问题的原因。我有大约 300 个项目和成千上万的用户。我想我需要 SIMD 或类似的东西才能在合理的时间内运行。 @RyanPeschel 。 . .你有指定的索引吗? 是的,我尝试使用 The Impaler 提到的覆盖索引,但它似乎根本没有提高查询速度。 @RyanPeschel 。 . .这不是我回答中的索引。 你是对的。好的,我也做了一个,但性能还是一样。

以上是关于一种更有效的方法来总结 postgres 中列之间的差异?的主要内容,如果未能解决你的问题,请参考以下文章

为啥一种方法比另一种更有效?

Python - 寻找一种更有效的方法来重新编写字典中的键

有没有一种更有效的方法来枚举python或R中离散随机变量的每个可能结果的概率?

如何简化 postgres 数据和 java 对象/json 有效负载之间的映射(反之亦然)

记录--一种更现代的深浅拷贝方法

Postgres 表中列的顺序会影响性能吗?