我有一個7列的表,其中5個將爲空。我將在int
,text
,date
,boolean
和money
數據類型上有空列。這張表格將包含數百萬行有許多空值的行。恐怕空值將佔據空間。在PostgreSQL中可空列是否佔用額外的空間?
另外,你知道如果Postgres索引空值?我想阻止它索引空值。
我有一個7列的表,其中5個將爲空。我將在int
,text
,date
,boolean
和money
數據類型上有空列。這張表格將包含數百萬行有許多空值的行。恐怕空值將佔據空間。在PostgreSQL中可空列是否佔用額外的空間?
另外,你知道如果Postgres索引空值?我想阻止它索引空值。
基本上,NULL
值佔用1位在NULL位圖中。但它並不那麼簡單。
空位圖(每行)僅當該行中至少有一列包含NULL
值時才存在。這可能會導致9列或更多列的表中出現悖論效應:將第一個NULL
值分配給列可能佔用磁盤空間而不是寫入數值。相反,如果最後一列變爲非空,則會爲該行刪除空位圖。
在物理上,最初爲空的位圖佔用1字節的HeapTupleHeader
(23字節)之間的和實際的列數據或行OID
(如果仍然應該使用) - 這總是開始在MAXALIGN
的倍數(通常爲8字節)。這留下了1字節由初始空位圖使用的填充。
實際上對於8列或更少的表格,NULL存儲空間是完全免費的。
之後,另一個MAXALIGN
字節(通常爲8)分配給下一個MAXALIGN * 8
列(通常爲64)。等
更多細節in the manual並根據這些相關的問題:
一旦你理解數據類型的對齊填充,您可以進一步優化存儲:
但情況是罕見的,你可以節省大量的空間。通常這是不值得的。
@Daniel已經涵蓋了對索引大小的影響。
我相信每個人都會使用位圖中的單個位作爲行。請參閱:http://www.postgresql.org/docs/9.0/static/storage-page-layout.html#HEAPTUPLEHEADERDATA-TABLE
NULL
值是否到達索引或至少取決於索引的類型。 基本上,這將是YES爲btree
和gist
的索引類型,NO爲hash
,它似乎YES或取決於PostgreSQL的版本NO爲gin
索引類型。
pg_catalog.pg_am
表中有一個布爾型列amindexnulls
,它載有這些信息,但它已經在9.1中消失了。可能因爲指標在PG改進中變得更加複雜。
在您的數據的具體情況下,最好的方法是測量索引的大小差異,使用pg_relation_size('index_name')
函數,在完全爲NULL的內容和完全非NULL的內容之間,使用精確的PG版本,確切的數據類型,確切的索引類型和定義。並且可能知道,任何這些參數的未來變化都可能改變結果。
但在任何情況下,如果你「只是」想避免索引空值,它總是可以創建一個部分索引:
CREATE INDEX partial_idx(col) ON table WHERE (col is not null)
這將需要更少的空間,但是否這是怎麼回事幫助或不利用查詢的性能取決於這些查詢。
+1有洞察力。對於部分索引,重要的是要注意,如果查詢計劃程序可以驗證查詢中是否包含該條件,那麼它們只能被查詢計劃程序使用。查詢規劃器很聰明,但在這方面無法解決複雜的邏輯。或多或少逐字匹配'WHERE'子句以確保可以使用索引(可能有更多條件的「AND」編輯)。 [手冊中的詳細信息](http://www.postgresql.org/docs/current/interactive/indexes-partial.html)。 –
很酷......謝謝您的深刻解答 – Luke101
「對於8列或更少的表格,NULL存儲空間是完全免費的。」 - 如果只有一列保留爲空,會怎麼樣?這意味着只有1個字節的空位圖纔會保存1位? – Dejell
如果存在任何空值,並且有足夠的字節來覆蓋所有列,並且加上「MAXALIGN」的下一個倍數,則會出現空位圖。 –
謝謝歐文。仍然不確定 - 如果我沒有任何空值,該怎麼辦?它仍然會在那裏嗎? (多對多表) – Dejell