2010-06-22 42 views
18

我有7個8位整數值,我想存儲在Postgres中。 Pg不提供單字節整數類型SMALLINT或2字節,它是最小的整型數據類型。無論如何,我可以存儲我的7位8位數字並節省空間嗎?是否可以在Postgres中存儲1個字節的數字?

具有7元素數組的數組類型會更緊湊嗎?或者,我是否應該對我的7個數字進行二進制表示(例如,使用Perl中的pack)並將其存儲在單個bytea字段中?

其他建議?

回答

17

鑑於PostgreSQL中任何行的開銷是23 bytes(HeapTupleHeaderData),如果您真的關心少量空間,那麼您可能選擇了錯誤的方式來存儲數據。無論如何,因爲所有更復雜的類型都有自己的開銷(bytea增加了四個字節的開銷,例如比特串5到8),唯一的方法就是使用bigint( 8個字節),對每個值進行數字移位並將結果進行「或」運算。您可以使用bit string operations來實現代碼更簡單 - 計算爲位串,然後在存儲之前轉換爲bigint - 或者如果您希望速度更好,可以手動乘法/添加。例如,這裏是你如何存儲兩個字節一起到兩個字節的結構,然後他們弄回來:

int2 = 256 * byte1 + byte2 
byte1 = int2/256 
byte2 = int2 % 256 

可以擴展相同的想法到存儲其中7的方式。檢索開銷仍然很糟糕,但實際上你會在這個過程中節省一些空間。但不僅僅是與行標題相關。

+3

每行有6個1字節整數(?),3個2字節整數(SMALLINT)和2個4字節整數(INT)。這是每行總共20個字節,加上Pg的開銷。由於Pg僅提供SMALLINT作爲最小值,因此我的6個1字節值將佔用12個字節。我正在尋找這些可能的替代方案。節省6個字節乘以1200億行約670 GB(如果我的計算是正確的)。也就是說,我確實需要分別取出這些值,所以我可能會以檢索速度支付價格。我需要平衡這兩者。在更大的方案中,0.7 TB並不是一個巨大的空間。 – punkish 2010-06-22 15:13:51

2

你可會查找使用這些值的記錄?

如果是 - 使用普通的數據類型,如int4(如果你在64位體系結構,甚至使用int8)。

如果不是 - 首先問自己 - 在Pg中存儲這個值有什麼意義?你可以使用bytea(複雜的I/O)或比特串(甚至更復雜的I/O),但是有什麼意義?你將擁有多少十億條記錄?你真的檢查過小的數據類型是否佔用較少的空間(提示:它沒有,檢查它 - 涉及到數據對齊問題)?你的印象是,較小的數據類型更快(它不是,比較兩個int2值比在32位體系結構上的兩個int4值要複雜得多)。

+1

您有一些有效的問題,我可以通過提供更多信息來搶先。我有6個8位值,預計有120億行。因此,儘可能節約空間的願望。 – punkish 2010-06-22 14:46:59

+4

實際上它確實節省了存儲int2和int4的空間。我在8.4上進行了測試,每個元組存儲7 x int2 = 38個字節; 7個字符(1)= 41個字節; 7 x int4 = 52個字節。 – 2010-06-22 18:43:49

1

首先你問了7,但現在是6字節。六個8位值完全對應於MAC地址大小和PostgreSQL的內置類型macaddr。您可以使用MAC語法f.i插入這些字節。 A1-B2-C3-D4-E5-F6。

4

pg_catalog.char(另一種表示法 - 「char」)類型,它只使用1個字節來存儲它的值。

select pg_column_size('A'); 
pg_column_size 
---------------- 
       2 
(1 row) 

select pg_column_size('A'::"char"); 
pg_column_size 
---------------- 
       1 
(1 row) 
+1

「char」類型只能從0到127「計數」。試試這個:從generate_series(0,127)s(i)'select i,ascii(i ::「char」)。現在將127更改爲128. – 2013-02-21 14:03:55

+4

@ClodoaldoNeto不正確,它可以從-128到127計數,嘗試從generate_series(-128,127)s(i)中選擇i,ascii(i ::「char」)' – TruongSinh 2014-11-03 14:34:29

相關問題