【发布时间】: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;但查询似乎仍然需要相同的时间。
标签: sql postgresql optimization vectorization simd