为啥 PostgreSQL 9.2.1 可以存储大于 2GB 的大对象?

Posted

技术标签:

【中文标题】为啥 PostgreSQL 9.2.1 可以存储大于 2GB 的大对象?【英文标题】:How come PostgreSQL 9.2.1 can store Large Object bigger than 2GB?为什么 PostgreSQL 9.2.1 可以存储大于 2GB 的大对象? 【发布时间】:2013-06-11 08:27:25 【问题描述】:

我对 PostgreSQL 和数据库完全陌生,正在尝试对大对象进行一些测试。

我刚刚发现可以将 8GB 的​​文件保存到 Postgres。

但是文档说大型对象(pg_largeobject 存储)的最大值为 2GB。

http://www.postgresql.org/docs/9.2/static/lo-intro.html

我错过了什么吗?

选择version() 显示:

x86_64-unknow-linux-gnu 上的 PostgreSQL 9.2.1,由 gcc (GCC) 4.4.6 20120305 (Red Hat 4.4.6-4) 编译,64 位

如果您有兴趣,这是我的代码:

private long insertLargeObject(UsSqlSession session, FileEntity fileEntity) throws SQLException, FileNotFoundException, IOException
    LargeObjectManager lobj = getLargeObjectAPI(session);

    long oid = lobj.createLO();
    LargeObject obj = lobj.open(oid, LargeObjectManager.WRITE);

    try(FileInputStream fis = new FileInputStream(fileEntity.getFile()))
        int bufSize = 0x8FFFFFF;
        byte buf[] = new byte[bufSize];
        int s = 0;
        int tl = 0;
        while( (s = fis.read(buf, 0, bufSize)) > 0 ) 
            obj.write(buf, 0, s);
            tl += s;
        
    

    obj.close();
    return oid;

更新:

pg_largeobject 的大小为 11GB,pg_largeobject_metadata 表示只有一行,这意味着只有一个大对象存在。

select sum(length(lo.data)) 
from pg_largeobject lo 
where lo.loid=1497980;

返回4378853347

更新:

public File findLargeObject(UsSqlSession session, long oid) throws SQLException, FileNotFoundException, IOException
    LargeObjectManager lobj = getLargeObjectAPI(session);
    LargeObject obj = lobj.open(oid, LargeObjectManager.READ);

    int bufSize = 0x8FFFFFF;
    byte buf[] = new byte[bufSize];
    int s = 0;
    int tl=0;

    File file = new File("e:/target-file");
    try(FileOutputStream output = new FileOutputStream(file))

        while( (s = obj.read(buf, 0, bufSize)) > 0 )
            output.write(buf, 0, s);
            tl += s;
        
        output.flush();
    

    obj.close();
    return file;

【问题讨论】:

我自己也很好奇这个。您能否尝试this answer 中的一些东西来检查它在服务器端是否真的是 8 GB,只是为了确定? 是的...如果您使用的是 9.2,我不相信该对象真的是您认为的大小,因为所有大小都是 32 位有符号整数。用于大对象的 64 位整数 API 即将推出;我认为它在 9.3 中,但需要仔细检查。 +1 感谢您提供正确的版本和相关代码 @jpmc26 pg_large_object的大小是11GB,pg_largeobject_metadata说有一行。 @jpmc26 select sum(length(lo.data)) from pg_largeobject lo where lo.loid=1497980; 返回4378853347。我会更新问题。 假设是字节,大约是 4 GB。听起来好像有什么可疑的事情发生在周围。 (通知@CraigRinger,因为我显然不合群。=)) 【参考方案1】:

我认为正确的答案是:“您的 PostgreSQL 是在 int64 支持下构建的,因此您可以在一个 LO 中写入超过 2GB 的数据。但您可能会遇到阅读问题。”

尝试阅读 Tom Lane 的回复:http://postgresql.1045698.n5.nabble.com/Large-objects-td2852592.html 关注关于“lo_seek64”和“lo_tell64”函数的随机咆哮。

【讨论】:

很好的发现...这是一个合理的解释。 “哎呀。让人们将数据写入他们无法从其中取回的地方似乎是双倍的不利。” 作者:罗伯特·哈斯 @CraigRinger 我刚刚通过写入和读取 3GB 文件来运行另一个测试。 Postgres jsut 工作正常。 select sum(length(lo.data)) from pg_largeobject lo where lo.loid=1497987; 返回3350906766 是的,但是您可以实际获取数据 loreadlo_lseek 等吗?这些没有bigint 版本。 @CraigRinger 我可以从 Postgres 中读取它。请参阅我的更新代码以供阅读。

以上是关于为啥 PostgreSQL 9.2.1 可以存储大于 2GB 的大对象?的主要内容,如果未能解决你的问题,请参考以下文章

为啥在 PostgreSQL 存储过程中查询没有“结果数据的目标”?

为啥我在从 Java 批量执行 PostgreSQL 存储过程时收到错误消息,提示“未预期结果”?

为啥我在postgresql的json数据中查询,速度会比mysql慢很多

Postgresql存储二进制大数据文件

为啥 Django 更喜欢 Postgresql? [复制]

为啥我在 postgresql 中的视图不使用索引?