最近在项目中遇到一个问题,让我排查了很久,在这里记录一下。
在项目中需要存储的数据有的很大,所在建表的时候该字段就用大文本记录(text),java中用 @Lob 注释属性字段。使用jap自动建表的方式,结果造成有写情况下回记录非常多的数据,造成数据库磁盘占用率高且张得很快。
有一个现象是,查看表占用的空间时显示表占用空间很小。但是查看表所在的数据库时,就会发现数据库占了很大的空间。
原因就是,记录了大量的text数据。因为text字段存储的数据并不是真正的数据,只是一个类似于索引的字段(loid),实际的数据是存储在 pg_largeobject 表中的,自建表中的text的值表明该行的这个text类型的真实数据在==pg_largeobject ==表中的标记。
换句话说,如果你通过jpa机制自动建了一个表 info 其中 data是 text 类型。
@Entity
@Table(name = "INFO")
@Comment("订阅表")
@Data
@EntityListeners(AuditingEntityListener.class)
public class InfoEntity{
@Id
@Column(name = "id", unique = true, nullable = false, length = 64)
private String id;
@Column(name = "data")
@Lob
private String data;
}
在数据库中,jpa自动建表时,@Lob 注解会自动被标识为text字段。
在业务中,会向这张表存入数据。实际上,INFO表中的data字段只是存了一个标识,数据库叫 loid ,它是 Info表中对应的这条数据的data字段值,在 pg_largeobject 中的标识。通过这个 loid 值,可以查到对应的data的实际值。
要想让存入info表中的data数据不存入 pg_largeobject表,有一种可行的办法是在jpa自动建表之前将表建好。但是,博主还没有验证过这个方法。后期在验证。
以下是一些知识点,是博主当初不知道了,既然了解了。记录下来以免忘记。
一、 pg_largeobject 表位置:
postagreSql中 pg_largeobject 位于:对应的数据库 —> 目录 —> PostgreSQL —> 数据表。此外,该表好像只能用高级用户查看。而且需要使用postgresql自带对的工具来查看,第三方工具如navicate,博主没有研究过怎么看。
二、查看数据库的大小
查看多个数据库:
SELECT d.datname AS Name, pg_catalog.pg_get_userbyid(d.datdba) AS Owner,
CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')
THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))
ELSE 'No Access'
END AS SIZE
FROM pg_catalog.pg_database d
ORDER BY
CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')
THEN pg_catalog.pg_database_size(d.datname)
ELSE NULL
END DESC;
查看单个数据库
select pg_size_pretty(pg_database_size('databasename'));
三、 表空间
查看表空间:
select spcname from pg_tablespace;
查看表空间大小:
select pg_size_pretty(pg_tablespace_size('spcname'));
四、查看表的大小
SELECT relname, age(relfrozenxid) as xid_age, pg_size_pretty(pg_table_size(oid))
as table_size FROM pg_class WHERE relkind = 'r' ORDER BY pg_table_size(oid) DESC;