postgresql - 将 varbit 转换为 int 的其他方法?还有大金币?

标签 postgresql casting

这个函数是一种变通方法……没有什么能更好的性能

CREATE or REPLACE FUNCTION varbit_to_int(v varbit) RETURNS int AS $f$
  SELECT CASE bit_length(v)
    WHEN 1 THEN v::bit(1)::int
    WHEN 2 THEN v::bit(2)::int
    WHEN 3 THEN v::bit(3)::int
    ...
    WHEN 30 THEN v::bit(30)::int
    WHEN 31 THEN v::bit(31)::int
    WHEN 32 THEN v::bit(32)::int
    ELSE NULL::int
  END
$f$ LANGUAGE SQL IMMUTABLE;

bigint 同样的问题:

CREATE or replace FUNCTION varbit_to_bigint(p varbit) RETURNS bigint AS $f$
  SELECT CASE bit_length($1)
    WHEN 1 THEN $1::bit(1)::bigint
    WHEN 2 THEN $1::bit(2)::bigint
    WHEN 3 THEN $1::bit(3)::bigint
    ...
    WHEN 62 THEN $1::bit(62)::bigint
    WHEN 63 THEN $1::bit(63)::bigint
    WHEN 64 THEN $1::bit(64)::bigint
    ELSE NULL::bigint
  END
$f$ LANGUAGE SQL IMMUTABLE STRICT;

在循环中多次使用似乎是 CPU 浪费,只是为了避免“无法将类型位变化转换为整数”错误。也许外部 C 语言库可以执行此操作和其他有用的转换。


注意 选择 b'101'::bit(64)::bigint != b'101'::bigint;

最佳答案

我测试了几个具有内置功能的变体(仅针对 bigint),这个变体带有 OVERLAY()在我对 Postgres 11 的本地测试中结果是最快:

CREATE OR REPLACE FUNCTION varbit2bigint2(b varbit)
  RETURNS bigint AS
$func$
SELECT OVERLAY(bit(64) '0' PLACING b FROM 65 - bit_length(b))::bigint
$func$  LANGUAGE SQL IMMUTABLE;

其他候选人:

请注意空位串 ('') 到 0NULL 的不同转换。适应您的需求!

你的功能:

CREATE OR REPLACE FUNCTION varbit2bigint1(b varbit)
  RETURNS bigint AS
$func$
  SELECT CASE bit_length($1)
   WHEN  1 THEN $1::bit(1)::bigint
   WHEN  2 THEN $1::bit(2)::bigint
   WHEN  3 THEN $1::bit(3)::bigint
   WHEN  4 THEN $1::bit(4)::bigint
   WHEN  5 THEN $1::bit(5)::bigint
   WHEN  6 THEN $1::bit(6)::bigint
   WHEN  7 THEN $1::bit(7)::bigint
   WHEN  8 THEN $1::bit(8)::bigint
   WHEN  9 THEN $1::bit(9)::bigint
   WHEN 10 THEN $1::bit(10)::bigint
   WHEN 11 THEN $1::bit(11)::bigint
   WHEN 12 THEN $1::bit(12)::bigint
   WHEN 13 THEN $1::bit(13)::bigint
   WHEN 14 THEN $1::bit(14)::bigint
   WHEN 15 THEN $1::bit(15)::bigint
   WHEN 16 THEN $1::bit(16)::bigint
   WHEN 17 THEN $1::bit(17)::bigint
   WHEN 18 THEN $1::bit(18)::bigint
   WHEN 19 THEN $1::bit(19)::bigint
   WHEN 20 THEN $1::bit(20)::bigint
   WHEN 21 THEN $1::bit(21)::bigint
   WHEN 22 THEN $1::bit(22)::bigint
   WHEN 23 THEN $1::bit(23)::bigint
   WHEN 24 THEN $1::bit(24)::bigint
   WHEN 25 THEN $1::bit(25)::bigint
   WHEN 26 THEN $1::bit(26)::bigint
   WHEN 27 THEN $1::bit(27)::bigint
   WHEN 28 THEN $1::bit(28)::bigint
   WHEN 29 THEN $1::bit(29)::bigint
   WHEN 30 THEN $1::bit(30)::bigint
   WHEN 31 THEN $1::bit(31)::bigint
   WHEN 32 THEN $1::bit(32)::bigint
   WHEN 33 THEN $1::bit(33)::bigint
   WHEN 34 THEN $1::bit(34)::bigint
   WHEN 35 THEN $1::bit(35)::bigint
   WHEN 36 THEN $1::bit(36)::bigint
   WHEN 37 THEN $1::bit(37)::bigint
   WHEN 38 THEN $1::bit(38)::bigint
   WHEN 39 THEN $1::bit(39)::bigint
   WHEN 40 THEN $1::bit(40)::bigint
   WHEN 41 THEN $1::bit(41)::bigint
   WHEN 42 THEN $1::bit(42)::bigint
   WHEN 43 THEN $1::bit(43)::bigint
   WHEN 44 THEN $1::bit(44)::bigint
   WHEN 45 THEN $1::bit(45)::bigint
   WHEN 46 THEN $1::bit(46)::bigint
   WHEN 47 THEN $1::bit(47)::bigint
   WHEN 48 THEN $1::bit(48)::bigint
   WHEN 49 THEN $1::bit(49)::bigint
   WHEN 50 THEN $1::bit(50)::bigint
   WHEN 51 THEN $1::bit(51)::bigint
   WHEN 52 THEN $1::bit(52)::bigint
   WHEN 53 THEN $1::bit(53)::bigint
   WHEN 54 THEN $1::bit(54)::bigint
   WHEN 55 THEN $1::bit(55)::bigint
   WHEN 56 THEN $1::bit(56)::bigint
   WHEN 57 THEN $1::bit(57)::bigint
   WHEN 58 THEN $1::bit(58)::bigint
   WHEN 59 THEN $1::bit(59)::bigint
   WHEN 60 THEN $1::bit(60)::bigint
   WHEN 61 THEN $1::bit(61)::bigint
   WHEN 62 THEN $1::bit(62)::bigint
   WHEN 63 THEN $1::bit(63)::bigint
   WHEN 64 THEN $1::bit(64)::bigint
   ELSE NULL::bigint
  END
$func$  LANGUAGE SQL IMMUTABLE;  -- no STRICT modifier

用“0”左填充文本表示:

CREATE OR REPLACE FUNCTION pg_temp.varbit2bigint3(b varbit)
  RETURNS bigint AS
$func$
SELECT lpad(b::text, 64, '0')::bit(64)::bigint
$func$  LANGUAGE SQL IMMUTABLE;

转换前的位移:

CREATE OR REPLACE FUNCTION varbit2bigint4(b varbit)
  RETURNS bigint AS
$func$
SELECT (bit(64) '0' || b << bit_length(b))::bit(64)::bigint
$func$  LANGUAGE SQL IMMUTABLE;

db<> fiddle here

相关:

您的反馈

It is not worst, it is faster!

EXPLAIN ANALYZE select 
  varbit_to_bigint(osm_id::bit(64)::varbit) 
from planet_osm_point limit 10000 ;
-- Planning time: 0.697 ms
-- Execution time: 1133.571 ms

EXPLAIN ANALYZE select 
  lpad(osm_id::bit(64)::varbit::text, 32, '0')::bit(64)::bigint 
from planet_osm_point limit 10000;
-- Planning time: 0.105 ms
-- Execution time: 26.429 ms

您在问题中显示了一个带有 bigint 函数变体的 STRICT 修饰符(不确定为什么它与 不同整数变体)。如果这代表您实际测试的函数,我预计大部分观察到的性能差异是由于添加的 STRICT 修饰符阻止了函数内联Quoting the Postgres Wiki:

if the function is declared STRICT, then the planner must be able to prove that the body expression necessarily returns NULL if any parameter is null. At present, this condition is only satisfied if: every parameter is referenced at least once, and all functions, operators and other constructs used in the body are themselves STRICT.

这似乎严重损害了您的功能 - 虽然我的赢家似乎没有受到影响,而其他两个变体甚至快了 10%。与 STRICT 功能相同的 fiddle :

db<> fiddle here

相关:

我建议您在使用和不使用 STRICT 修饰符的情况下重新测试自己看看。

关于postgresql - 将 varbit 转换为 int 的其他方法?还有大金币?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56119704/

相关文章:

postgresql - 如何在 PostgreSQL 中创建自定义时区?

java - 在运行时解析泛型变量时如何避免未经检查的强制转换?

cocoa - 将 NSMutableArray 转换为 sudzc 中的自定义对象数组

c# - 转换为抽象通用基类

php - 如何从 php(初学者)设置 postgresql?

sql - 如何使用PostgreSQL显示数据库查询中的记录

postgresql(远程)连接被拒绝

python - 没有在 postgresql 中的表上执行查询

java - JAVA中的隐式接口(interface)、类转换

c++ - 如何将 C++ 类转换为内部类型