2014-10-08 68 views
0
存儲問題

說我有一個3列的表格:varchar(20), hstore, smallint與鍵,值數據類型,特別是Hstores在PostgreSQL

現在,如果我插入如下:"ABCDEF", "abc=>123, xyz=>888, lmn=>102", 5

多少空間將記錄採取的PostgreSQL ? hstore是否以純文本形式存儲? 因此,如果我有一百萬條記錄,按鍵(abc,xyz,lmn)所佔用的空間將被複制到全部的記錄中?

我在問這個,因爲我有一個用例,我需要存儲未知數的鍵值對;每把鑰匙需要花費20B的時間,並且價值不超過smallint範圍。

問題是記錄的數量是巨大的,每天大約9000萬。 Key和Value對的數量是〜400。這很快導致存儲問題,因爲只有一天的數據總計高達800GB左右;與巨大的百分比是由所有記錄重複的鑰匙。

因此,考慮到有400個鍵/值對,記錄中的單個Hstore(如果以純文本形式存儲)將需要400 * 22個字節。乘以90萬,即737GB。 如果以2字節整數存儲在正常列中,則只需67GB。

HStores是否不適合此用例?我有什麼選擇可以幫助我解決這個存儲問題嗎?我知道這是一個很大的問題,我可能只需要使用常規的列式存儲解決方案,並放棄由關鍵價值提供的靈活性。

+0

我認爲hstore像其他任何可變長度數據類型一樣有資格進行壓縮:http://www.postgresql.org/docs/9.3/static/storage-toast.html(即將推出的9.4具有更高效的hstore存儲如果我沒錯的話)。但是如果你有一個「*跨所有記錄*的重複百分比很大的鍵」,那麼這聽起來更像是你想將它們存儲在一個單獨的表(和一個常規列)中,並使用一個外鍵來避免重複。 – 2014-10-08 08:05:29

回答

1

記錄在PostgreSQL中佔用多少空間?

要獲取原始的未壓縮大小:

SELECT pg_column_size(ROW('ABCDEF', 'abc=>123, xyz=>888, lmn=>102'::hstore, 5)); 

但由於TOAST compressed out-of-line storage可能不是在磁盤上的大小...但它往往是:

CREATE TABLE blah(col1 text, col2 hstore, col3 integer); 

INSERT INTO blah (col1, col2, col3) 
VALUES ('ABCDEF', 'abc=>123, xyz=>888, lmn=>102'::hstore, 5); 

regress=> SELECT pg_column_size(blah) FROM blah; 
pg_column_size 
---------------- 
      84 
(1 row) 

如果您在這裏使用了一個更大的值hstore,它可能會被壓縮和存儲在一行中。在這種情況下,尺寸取決於它的可壓縮程度。

hstore被存儲爲純文本嗎?

不,這是一種二進制格式,但也不是壓縮;鍵/值是純文本。

因此,如果我有一百萬條記錄,鍵(abc,xyz,lmn)所佔用的空間將會在所有記錄中被複制?

正確。每個hstore值都是獨立值。它與系統中任何地方的任何其他值都沒有關係。這就像textjson或其他任何東西。沒有一種中央密鑰索引或類似的東西。

演示:

CREATE TABLE hsdemo(hs hstore); 

INSERT INTO hsdemo(hs) 
SELECT hstore(ARRAY['thisisthefirstkey', 'thisisanotherbigkey'], ARRAY[x::text, x::text]) 
FROM generate_series(1,10000) x; 

SELECT pg_size_pretty(pg_relation_size('hsdemo'::regclass)); 
-- prints 992kb 

INSERT INTO hsdemo(hs) 
SELECT hstore(ARRAY['thisisthefirstkey', 'thisisanotherbigkey'], ARRAY[x::text, x::text]) 
FROM generate_series(10000,20000) x; 

SELECT pg_size_pretty(pg_relation_size('hsdemo'::regclass)); 
-- prints 1968kb, i.e. near doubling for double the records. 

因此,如果你有很多高度重複的大按鍵和小的值,你應該看看一個規範化模式(是的,甚至EAV)。

但是,請注意,PostgreSQL每行的開銷超過20個字節,因此您可能無法獲得像預期的那樣通過存儲大量短行而不是像hstore之類的東西。

你總是可以妥協 - 保留一個全鍵名的查找表,並將它與一個短hstore鍵相關聯。因此,您的應用程序基本上會壓縮每個hstore中的密鑰。

+0

這是非常有用的信息,非常感謝..!所以如果我理解正確,在一個非索引的'hstore'上有200個鍵值對(在8000萬行的表中);如果我從MYTABLE(其中WHERE date 'somekey',它將會非常慢,比如'SELECT mykeycolumn from MYTABLE where date user1265125 2014-10-08 11:41:56

+0

@ user1265125是的,沒有索引它可能會很慢。支持hstore的GIN和GiST索引通常也比普通的b-tree索引慢一些。 * Howevever * Pg不一定會對所有200個鍵進行線性搜索; 'hstore'有一個內部查找表(這是一個散列表)。查看hstore源代碼中的文檔和註釋以獲取更多詳細信息。 – 2014-10-08 15:26:51

相關問題