2012-08-27 46 views
18

我有一個7列的表,其中5個將爲空。我將在int,text,date,booleanmoney數據類型上有空列。這張表格將包含數百萬行有許多空值的行。恐怕空值將佔據空間。在PostgreSQL中可空列是否佔用額外的空間?

另外,你知道如果Postgres索引空值?我想阻止它索引空值。

回答

34

基本上,NULL值佔用1位在NULL位圖中。但它並不那麼簡單。

空位圖(每行)僅當該行中至少有一列包含NULL值時才存在。這可能會導致9列或更多列的表中出現悖論效應:將第一個NULL值分配給列可能佔用磁盤空間而不是寫入數值。相反,如果最後一列變爲非空,則會爲該行刪除空位圖。

在物理上,最初爲空的位圖佔用1字節HeapTupleHeader(23字節)之間的和實際的列數據或行OID(如果仍然應該使用) - 這總是開始在MAXALIGN的倍數(通常爲8字節)。這留下了1字節由初始空位圖使用的填充。

實際上對於8列或更少的表格,NULL存儲空間是完全免費的
之後,另一個MAXALIGN字節(通常爲8)分配給下一個MAXALIGN * 8列(通常爲64)。等

更多細節in the manual並根據這些相關的問題:

一旦你理解數據類型的對齊填充,您可以進一步優化存儲:

但情況是罕見的,你可以節省大量的空間。通常這是不值得的。

@Daniel已經涵蓋了對索引大小的影響。

+0

「對於8列或更少的表格,NULL存儲空間是完全免費的。」 - 如果只有一列保留爲空,會怎麼樣?這意味着只有1個字節的空位圖纔會保存1位? – Dejell

+0

如果存在任何空值,並且有足夠的字節來覆蓋所有列,並且加上「MAXALIGN」的下一個倍數,則會出現空位圖。 –

+0

謝謝歐文。仍然不確定 - 如果我沒有任何空值,該怎麼辦?它仍然會在那裏嗎? (多對多表) – Dejell

11

NULL值是否到達索引或至少取決於索引的類型。 基本上,這將是YESbtreegist的索引類型,NOhash,它似乎YES或取決於PostgreSQL的版本NOgin索引類型。

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) 

這將需要更少的空間,但是否這是怎麼回事幫助或不利用查詢的性能取決於這些查詢。

+7

+1有洞察力。對於部分索引,重要的是要注意,如果查詢計劃程序可以驗證查詢中是否包含該條件,那麼它們只能被查詢計劃程序使用。查詢規劃器很聰明,但在這方面無法解決複雜的邏輯。或多或少逐字匹配'WHERE'子句以確保可以使用索引(可能有更多條件的「AND」編輯)。 [手冊中的詳細信息](http://www.postgresql.org/docs/current/interactive/indexes-partial.html)。 –

+0

很酷......謝謝您的深刻解答 – Luke101