2015-09-03 77 views
1

在我當前的項目中,我們有許多存儲在postgres數據庫中的小型表。最常見的操作是導出一個CSV文件,該文件是通過公用密鑰加入的某些/所有表中的列的一個選擇。每列可以是任何數據類型,因爲它由用戶輸入系統的內容決定。將非常寬的(超過1600列)查詢導出爲CSV

我通過創建X列寬的表實現結果,然後將數據複製到其中,其中X是用戶選擇的列數。

我的問題是,用戶經常想要導出數以千計的列。我很快就達到了postgres允許我創建的最大表格,這是1600.據我所知,這受到頁面大小,列數/每列內存大小的限制。我可以增加頁面大小,但我最終會繼續達到這個限制。

我的新解決方案是將多個表中的輸出中斷,其中每個表都被寫入其自己的csv文件。關鍵列將在所有文件中,所以其他一些程序可能會索引和鏈接數據。

我的問題是,如何確定每列將佔用多少空間?每種數據類型是否佔用線性數量的內存?有沒有我需要考慮的填充物?

+1

用戶請求1600列?這聽起來像某些東西沒有正確表示。它通常是很大的行數。什麼情況需要這麼多列? – RealSkeptic

+0

這些數據是研究數據。每一行是一個主題,每一列都是一個測量變量。每張小桌子都是在特定時間拍攝的數據集。用戶有一個非常「簡單」的方法,基本上想要查看所有主題或這些變量的子集的所有變量,例如「所有變量是某種類型的測試的結果(這仍然等於幾千)」。 – Andy

+0

實際上,我想每次只導出一個主題,這樣我就可以導出一個2列鍵對樣式表,但用戶不會滿足任何小於表格導出的問題,所以我會做成千上萬的單一導出表,然後必須在客戶端格式化它們,這是我無法想象的高性能。 – Andy

回答

0

你甚至可以\copy (SELECT ...)一排寬於1664列不:

ERROR: target lists can have at most 1664 entries 

所以你將不得不尋找不同的方式來做到這一點。

增加PostgreSQL的頁面大小可能會讓問題不堪重負,但無法解決您的問題,只會延遲它,並在此過程中創建大量其他問題。非默認塊大小測試不多,可能表現不佳,並且在做PITR /備份和恢復時很痛苦等。

考慮使用像Talend Studio,Pentaho Kettle或CloverETL這樣的ETL工具處理導出並加入數據。


My question is, how do I determine how much space each column will take up?

使用pg_column_size。請注意,有些類型可以按照TOAST documentation存儲壓縮和非線性,所以pg_column_size(somecol)pg_column_size('text_of_somecol')都是不一樣的東西。此外,pg_column_size不會報告超線程存儲的TOAST-able類型的吐司指針的寬度,它會報告存儲的大小。所以對於TOASTable(可變長度)的類型,你必須根據所記錄的大小來解決它自己:

Allowing for the varlena header bytes, the total size of a TOAST pointer datum is therefore 18 bytes regardless of the actual size of the represented value.

的基本類型是簡單的固定寬度類型。個float4,是float8,INT4,INT8,布爾,"char"(這是不是一回事作爲charcharacter,引號是顯著),存儲文本或文本數據等是可變的寬度等

任何。 textvarchar,bytea等都是可以烤制的。

您可以通過查詢pg_type目錄來了解具體情況。有關這些字段的含義,請參閱文檔。

Does each datatype take up a linear amount of memory?

如上所述,它取決於類型。

Is there any padding I need to take into consideration?

是的。它是特定於類型的,並涉及內存對齊要求。請參閱pg_type目錄以瞭解對齊信息。

pg_column_size在整行上,例如, select pg_column_size(x) FROM mytable可以提供信息。

欲瞭解更多詳情,請參閱關於src/backend/access/common/heaptuple.c的評論。