postgresql 在Postgres中将bytea转换为SQL中的int[]

a5g8bdjr  于 2023-11-18  发布在  PostgreSQL
关注(0)|答案(1)|浏览(128)

我在PostgreSQL数据库中的表在名为vector的列中存储了大量的整数数组。由于所有的数字都适合从-128到127的范围,并且为了保存空间,我使用bytea类型。我需要使用pgvector扩展提供的点积距离运算符<#>,例如:

select id
from MyTable
order by vector<#>key
limit 10;

字符串
然而,这个操作符不支持bytea类型。我想把我的向量转换成int[],然后可以转换成pgvector支持的vector类型。
我认为将bytea转换为int[]的一般方向可能是沿着以下路线:

SELECT string_to_array(encode(vector, 'escape'), '\\')::int[]
FROM MyTable;


我如何修改它以使转换工作?

bkhjykvo

bkhjykvo1#

您可以使用generate_series()加入并使用get_byte()函数:

WITH b(b) AS (VALUES (BYTEA '\x55FF1200DEADBEEF'))
SELECT array_agg(get_byte(b.b, g.i) - 128)
FROM b
   CROSS JOIN LATERAL generate_series(0, length(b) - 1) AS g(i);

            array_agg             
══════════════════════════════════
 {-43,127,-110,-128,94,45,62,111}
(1 row)

字符串
这将是缓慢和低效的,但这是可以预料的,如果你试图不惜一切代价保存空间。
我建议使用smallint[],它使用每个数字2个字节。
如果你运行的是PostgreSQL v15或更高版本,你也可以使用内部数据类型"char"的数组,它每个元素只占用一个字节:

SELECT ARRAY[-43,127,-110,-128,94,45,62,111]::"char"[];

                 array                  
════════════════════════════════════════
 {"\\325",\x7F,"\\222","\\200",^,-,>,o}
(1 row)


要获取单个元素,可以使用

SELECT (ARRAY[-43,127,-110,-128,94,45,62,111]::"char"[])[3]::integer;

 array 
═══════
  -110
(1 row)


"char"[]每个元素使用一个字节,每个数组使用21个字节的开销(bytea每个值的开销为一个或四个字节,具体取决于大小)。

相关问题