我正在运行PostgreSQL 9.6,并且正在以下表结构上进行实验:
CREATE TABLE my_bit_varying_test (
id SERIAL PRIMARY KEY,
mr_bit_varying BIT VARYING
);
只是为了了解如果同时重置100,000位数据上的位,我可以期待多少性能,我编写了一个小的PL / pgSQL块,如下所示:
DO $$
DECLARE
t BIT VARYING(100000) := B'0';
idd INT;
BEGIN
FOR I IN 1..100000
LOOP
IF I % 2 = 0 THEN
t := t || B'1';
ELSE
t := t || B'0';
end if;
END LOOP ;
INSERT INTO my_bit_varying_test (mr_bit_varying) VALUES (t) RETURNING id INTO idd;
UPDATE my_bit_varying_test SET mr_bit_varying = set_bit(mr_bit_varying, 100, 1) WHERE id = idd;
UPDATE my_bit_varying_test SET mr_bit_varying = set_bit(mr_bit_varying, 99, 1) WHERE id = idd;
UPDATE my_bit_varying_test SET mr_bit_varying = set_bit(mr_bit_varying, 34587, 1) WHERE id = idd;
UPDATE my_bit_varying_test SET mr_bit_varying = set_bit(mr_bit_varying, 1, 1) WHERE id = idd;
FOR I IN 1..100000
LOOP
IF I % 2 = 0 THEN
UPDATE my_bit_varying_test
SET mr_bit_varying = set_bit(mr_bit_varying, I, 1)
WHERE id = idd;
ELSE
UPDATE my_bit_varying_test
SET mr_bit_varying = set_bit(mr_bit_varying, I, 0)
WHERE id = idd;
end if;
END LOOP ;
END
$$;
但是,当我运行PL / pgSQL时,需要花几分钟的时间才能完成,并且将其范围缩小到了更新表的for循环中。由于BIT VARYING
列上的压缩,它运行缓慢吗?有什么方法可以提高性能?
编辑这是一个模拟的简化示例。实际上,这是因为我有成千上万的作业正在运行,每个作业都需要报告其状态,每几秒钟更新一次。
现在,我可以对其进行归一化处理,并拥有一个“运行状态”表,该表可以保存所有工作人员及其状态,但是这将涉及存储成千上万的行。因此,我的想法是我可以使用位图存储客户端和状态,并且掩码会按顺序告诉我哪些已运行,哪些已完成。因为我不需要确切地知道哪个客户端发生了故障,只需要知道存在一个故障,就可以将前位用作“错误位”。
例如,您可能有5个工人从事一项工作。如果它们全部完成,则状态将为“ 01111”,表示所有作业都已完成,并且没有一个失败。如果2号工作人员失败,则状态为“ 111110”,表明存在错误,除最后一个工作人员外,所有工作人员均已完成。
因此,您可以将其视为处理大量作业状态的一种精心设计的方法。当然,我也有其他想法,但是即使走那条路,在将来,我仍然想知道如何快速更新变量,因为很好,我很好奇。
答案 0 :(得分:1)
您可以尝试使用基于集合的方法来替换第二个循环。基于集合的方法通常比循环更胖。使用generate_series()
获取索引。
UPDATE my_bit_varying_test
SET mr_bit_varying = set_bit(mr_bit_varying, gs.i, abs(gs.i % 2 - 1))
FROM generate_series(1, 100000) gs(i)
WHERE id = idd;
如果还没有索引,请考虑在my_bit_varying_test (id)
上创建索引。
答案 1 :(得分:1)
如果确实是TOAST压缩是您的问题,则可以为该表禁用它:
ALTER TABLE my_bit_varying_test SET STORAGE EXTERNAL;