Erw*_*ter 7 arrays postgresql performance
PostgreSQL可以在任何地方开始使用数组下标.
考虑这个创建一个包含3个元素的数组的示例,其中包含5到7的下标:
SELECT ('[5:7]={1,2,3}'::int[]);
Run Code Online (Sandbox Code Playgroud)
返回:
[5:7]={1,2,3}
Run Code Online (Sandbox Code Playgroud)
例如,你得到第一个元素的含义
SELECT ('[5:7]={1,2,3}'::int[])[5];
Run Code Online (Sandbox Code Playgroud)
我想规范化 任何给定的1维数组以从数组下标1开始.
我能想到的最好的:
SELECT ('[5:7]={1,2,3}'::int[])[array_lower('[5:7]={1,2,3}'::int[], 1):array_upper('[5:7]={1,2,3}'::int[], 1)]
Run Code Online (Sandbox Code Playgroud)
或者,同样,更容易阅读:
WITH x(a) AS (
SELECT '[5:7]={1,2,3}'::int[]
)
SELECT a[array_lower(a, 1):array_upper(a, 1)]
FROM x
Run Code Online (Sandbox Code Playgroud)
你知道更简单/更快或更优雅的方式吗?
为了测试性能,我提出了这个快速基准测试.
表有100k行,随机长度在1和11之间的简单整数数组:
CREATE TEMP TABLE t (a int[]);
INSERT INTO t -- now with actually varying subscripts
SELECT ('[' || g%10 || ':' || 2*(g%10) || ']={1'
|| repeat(','||g::text, g%10) || '}')::int[]
FROM generate_series(1,100000) g;
EXPLAIN ANALYZE
SELECT
substring(a::text, '{.*$')::int[] -- Total runtime: 949.304 ms
-- a[-2147483648:2147483647] -- Total runtime: 283.877 ms
-- a[array_lower(a, 1):array_upper(a, 1)] -- Total runtime: 311.545 ms
FROM t
Run Code Online (Sandbox Code Playgroud)
所以,是的,@ Daniel的想法稍快一些.
@Kevin的文字转换也有效,但不会赚很多分.
还有其他想法吗?
最终,Postgres 9.6出现了一些更优雅的东西。手册:
可以省略切片说明
lower-bound
符的 and/or ;upper-bound
缺失的界限由数组下标的下限或上限替换。例如:
所以现在很简单:
SELECT my_arr[:];
Run Code Online (Sandbox Code Playgroud)
在我的示例数组文字中,您需要用括号括起来以使语法明确:
SELECT ('[5:7]={1,2,3}'::int[])[:];
Run Code Online (Sandbox Code Playgroud)
与Daniel 的硬编码最大数组下标解决方案的性能大致相同- 这仍然是 Postgres 9.5 或更早版本的方法。
有一个更简单的方法是丑陋的,但我认为技术上正确:从数组中提取最大可能的切片,而不是具有计算边界的精确切片.它避免了两个函数调用.
例:
select ('[5:7]={1,2,3}'::int[])[-2147483648:2147483647];
Run Code Online (Sandbox Code Playgroud)
结果是:
int4 --------- {1,2,3}
归档时间: |
|
查看次数: |
1242 次 |
最近记录: |