記錄在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
值都是獨立值。它與系統中任何地方的任何其他值都沒有關係。這就像text
或json
或其他任何東西。沒有一種中央密鑰索引或類似的東西。
演示:
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中的密鑰。
我認爲hstore像其他任何可變長度數據類型一樣有資格進行壓縮:http://www.postgresql.org/docs/9.3/static/storage-toast.html(即將推出的9.4具有更高效的hstore存儲如果我沒錯的話)。但是如果你有一個「*跨所有記錄*的重複百分比很大的鍵」,那麼這聽起來更像是你想將它們存儲在一個單獨的表(和一個常規列)中,並使用一個外鍵來避免重複。 – 2014-10-08 08:05:29