在我目前的项目中,我们在postgres数据库中存储了许多小型表。最常见的操作是导出CSV文件,该文件是从公共密钥上连接的一些/所有表中选择的列。每列可以是任何数据类型,因为它由用户输入系统的内容决定。
我通过创建一个X列宽的表来实现结果,然后将数据复制到其中,其中X是用户选择的列数。
我的问题是用户经常想要导出数千列。我很快就达到了postgres允许我创建的最大表格,即1600.根据我的理解,这受到页面大小,列数/每列内存大小的限制。我可以增加页面大小,但我最终会继续达到这个限制。
我的新解决方案是在多个表中中断导出,其中每个表都写入其自己的csv文件。键列将位于所有文件中,因此其他一些程序可能会索引和链接数据。
我的问题是,如何确定每列占用多少空间?每种数据类型是否占用线性内存量?我需要考虑填充吗?
答案 0 :(得分:0)
除了1664列之外,您甚至不能\copy (SELECT ...)
行:
ERROR: target lists can have at most 1664 entries
所以你必须找到一种不同的方法来做到这一点。
增加PostgreSQL的页面大小可以解决问题,但不会解决您的问题,只是延迟它,并在此过程中创建许多其他问题。非默认块大小未经过大量测试,可能无法正常执行,并且在执行PITR /备份和还原/ pg_upgrade
等时非常痛苦。
考虑使用Talend Studio,Pentaho Kettle或CloverETL等ETL工具来处理导出并加入数据。
我的问题是,如何确定每列占用多少空间?
使用pg_column_size
。请注意,根据TOAST documentation,某些类型可以按压缩和脱节存储,因此pg_column_size(somecol)
和pg_column_size('text_of_somecol')
不是同一件事。此外,pg_column_size
不报告托管指针的宽度,以便在线外存储TOAST-able类型,它会报告存储的大小。因此,对于TOASTable(可变长度)类型,您必须根据记录的大小自行处理:
允许varlena头字节,TOAST指针数据的总大小因此是18个字节,而不管所表示的值的实际大小。
基元类型是简单的固定宽度类型。 float4,float8,int4,int8,bool,"char"
(与char
或character
不一样,引号很重要)等。
存储文本或类文本数据的任何内容都是可变宽度。 text
,varchar
,bytea
等都是非常好的。
您可以通过查询pg_type
目录来了解具体信息。有关字段的含义,请参阅文档。
每种数据类型是否占用线性内存量?
如上所述,这取决于类型。
我需要考虑填充吗?
是。它的类型特定并且与存储器对齐要求有关。有关对齐信息,请参阅pg_type
目录。
pg_column_size
,例如select pg_column_size(x) FROM mytable
可以提供信息。
有关gorey的详细信息,请参阅src/backend/access/common/heaptuple.c
上的评论。