我想要存储在Postgres中,每个记录有7个8位整数值。Pg不提供单字节整数类型SMALLINT或2字节,这是最小的整数数据类型。有没有什么办法可以存储我的7个8位数字并节省空间?
具有7元素数组的数组类型会更紧凑吗?或者,我是否应该对我的7个数字进行二进制表示(例如,在Perl中使用pack )并将其存储在一个bytea字段中?
还有其他建议吗?
发布于 2010-06-22 20:30:40
考虑到PostgreSQL中任何行的开销都是23 bytes (HeapTupleHeaderData),如果您真的关心这么少的空间,那么您可能选择了错误的数据存储方式。
无论如何,因为所有更复杂的类型都有它们自己的开销(bytea增加了4个字节的开销,例如,位串5到8),实现所需的唯一方法是使用bigint (8字节),对每个值进行数值移位并对结果进行OR运算。您可以使用bit string operations来简化代码--计算为位字符串,然后在存储之前转换为bigint --或者如果您希望速度更快,也可以手动进行乘法/加法。例如,下面是如何将两个字节一起存储到一个双字节结构中,然后再将它们取回:
int2 = 256 * byte1 + byte2
byte1 = int2 / 256
byte2 = int2 % 256你可以将同样的想法扩展到以这种方式存储其中的7个。检索开销仍然很大,但您实际上已经在此过程中节省了一些空间。但是仅仅相对于行头来说并不是很多。
发布于 2011-10-25 21:34:51
有一种pg_catalog.char (另一种符号- "char“)类型,它只使用一个字节来存储它的值。
select pg_column_size( 'A' );
pg_column_size
----------------
2
(1 row)
select pg_column_size( 'A'::"char" );
pg_column_size
----------------
1
(1 row)发布于 2018-03-19 06:15:59
"char"
这是PostgreSQL中的单字节类型,适合于-128,127的范围。来自the docs,
类型
"char"(请注意引号)与char(1)的不同之处在于它的只使用一个字节的存储空间。它在系统目录中作为一种简单的枚举类型在内部使用。
您可以在写入数据库之前从0-255范围内的任何输入中减去128,然后在从数据库读取时将其添加回输出,从而使其偏向-128,127。
-- works
SELECT (-128)::"char", 127::"char";
-- generates out of range
SELECT (-128)::"char";
SELECT 128::"char";
-- Shifts to unsigned range.
-- If you're going to be using "char"
-- review the results of this query!
SELECT
x::int AS "inputUnsigned",
chr(x) AS "extendedASCII",
-- this is the "char" types representation for that input.
signed::"char" AS "charRepresentation",
signed AS "inputUnsignedToSigned",
signed+128 AS "inputUnsignedToSignedToUnsigned"
FROM generate_series(1,255) AS gs(x)
-- Here we map the input in the range of [0,255] to [-128,127]
CROSS JOIN LATERAL ( VALUES (x::int-128) )
AS v(signed);输出的小摘录
inputUnsigned | extendedASCII | charRepresentation | inputUnsignedToSigned | inputUnsignedToSignedToUnsigned
---------------+---------------+--------------------+-----------------------+---------------------------------
....
190 | ¾ | > | 62 | 190
191 | ¿ | ? | 63 | 191
192 | À | @ | 64 | 192
193 | Á | A | 65 | 193
194 | Â | B | 66 | 194
195 | Ã | C | 67 | 195
196 | Ä | D | 68 | 196
...我们使用generate_series(1,255)只是因为chr(0)会抛出,因为您不能生成或输出ASCII (PostgreSQL使用NUL )
pguint扩展
Pguint是提供两个单字节表示的扩展,
int1 (signed)uint1 (未签名)https://stackoverflow.com/questions/3090138
复制相似问题