我打算从MySQL迁移到PostgreSQL,因为我想利用TimescaleDB。
一切都看起来不错,直到我检查了PostgreSQL(v11.2)与MySQL(v5.6)相比使用的存储大小。对于完全相同的行数(1,440,000)和内容:
MySQL和PostgreSQL的编号类似(即包括索引和其他约束),PostgreSQL + TimescaleDB具有在表中添加时间戳的开销。有关表如下所示:
create table cell(
cell_id serial not null
,ts timestamp not null
,parent_id int references parent( parent_id )
,instance_id smallint
,v float
,a float
,t float
,s1 float
,s2 float
,s3 float
,s4 float
,s5 float
,primary key( cell_id )
);
create index ix_cell_pid on cell( parent_id );
create index ix_cell_inst on cell( instance_id );
为什么PostgreSQL比MySQL占用更多的存储空间?
是否有某种方法可以将其显着降低到接近MySQL的水平?
答案 0 :(得分:3)
在您的情况下,添加timestamp
列应不超过11 MB(1440000 * 8字节,未添加填充)。
在测量尺寸之前,您是否在Postgres中运行了 VACUUM FULL
,以便进行合理的比较?我怀疑表和索引膨胀。
相关:
在MySQL中,数据类型 float
是占用 4个字节的单精度浮点类型。
在Postgres中,相同的float
是双精度浮点类型,占用 8个字节(别名:float8
或double precision
)。
那应该解释另外44 MB的差异。要将苹果与苹果进行比较,请创建带有4字节 real
列(别名为float4
)的Postgres表。注意与MySQL的区别,其中real
用于8字节浮点数!不幸的分歧。
MySQL手册:https://dev.mysql.com/doc/refman/8.0/en/storage-requirements.html
Postgres手册:https://www.postgresql.org/docs/current/datatype-numeric.html
相关:
您显示两个索引。根据它们的用途,一个多列索引可能可以在Postgres中替换两者-在这种特殊情况下,它所替换的两个索引中的 one 所占磁盘空间相同(在给定的规格下可节省约50 MB)。
create index ix_cell_pid on cell( parent_id, instance_id );
考虑:
答案 1 :(得分:1)
除了Erwin Brandstetter的回答:
通常还有一些隐藏的系统列要考虑(用于实现MVCC)以及其他元组信息,例如提示位(用于缓存行可见性)。
您可以使用pageinspect扩展名查看此信息,例如:
create extension pageinspect;
select * from heap_page_items(get_raw_page('cell', 0));
有关系统列的说明,请参见here。
您的索引也将包含空白,以允许更快地插入更多的元组。在CREATE INDEX docs中查找“ fillfactor”。