有序 postgresql 数组中大于 x 的最小值的位置(优化)

Posted

技术标签:

【中文标题】有序 postgresql 数组中大于 x 的最小值的位置(优化)【英文标题】:Position of the lowest value greater than x in ordered postgresql array (optimization) 【发布时间】:2021-06-08 22:54:53 【问题描述】:

看postgres函数array_position(anyarray, anyelement [, int])

我的问题类似,但我正在寻找大于元素的数组中第一个值的位置。我在小数组上运行它,但非常大的表。

这行得通:

CREATE OR REPLACE FUNCTION arr_pos_min(anyarray,real)
  RETURNS int LANGUAGE sql IMMUTABLE PARALLEL SAFE AS
'select array_position($1,(SELECT min(i) FROM unnest($1) i where i>$2))';

array_position 利用了我的数组是有序的这一事实,但第二部分没有。而且我觉得第二部分可能只是返回位置而无需重新查询。

我的数组只有 100 个元素长,但我必须运行数百万次,因此需要寻找性能提升。

建议表示赞赏。

【问题讨论】:

好吧,min() 并不真正关心订单。无论如何它都会查看所有值并返回最小值 不相关,但是:SQL函数可以使用参数名,不需要使用过时的$1和$1引用参数位置 【参考方案1】:

这似乎有点快

CREATE OR REPLACE FUNCTION arr_pos_min(p_input anyarray, p_to_check real)
  RETURNS int 
AS
$$
  select t.idx
  from unnest(p_input) with ordinality as t(i, idx) 
  where t.i > p_to_check
  order by t.idx
  limit 1
$$
LANGUAGE sql 
IMMUTABLE 
PARALLEL SAFE 
;

上面将使用数组中的值已经排序的事实。因此,按数组索引排序非常快。我不确定unnest() 在这种情况下是否保证按照它们存储在数组中的顺序返回元素。如果是这种情况,您可以删除 order by 并使其更快。

【讨论】:

谢谢 - 似乎工作。一件小事 - idx 是一个 bigint,所以需要重铸(或者函数只能返回一个大 int)【参考方案2】:

我认为没有比您的解决方案更有效的解决方案,除非您为此编写专用的 C 函数。

存储大型数组通常会导致性能下降。

【讨论】:

以上是关于有序 postgresql 数组中大于 x 的最小值的位置(优化)的主要内容,如果未能解决你的问题,请参考以下文章

算法4 整理

Perl实例---最小空间使用情况下合并有序数组

最小栈(栈设计)删除有序数组中的重复项(数组双指针)最大数(贪心字符串)

优化:从大于(或等于)`x`的数组返回最小值

剑指offer:旋转数组的最小数字

算法第二章上机实验报告