You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从Postgres导出180GB数据到CSV时内存耗尽及磁盘报错排查

问题:PostgreSQL导出180GB大表到CSV时内存耗尽+磁盘空间报错(本地磁盘有4TB剩余)

代码与环境信息

导出代码

def save_to_csv(self):
    query = str(self.Text1.get('1.0', 'end-1c'));
    now = datetime.datetime.now()
    timestamp_str = now.strftime("%Y-%m-%d_%H-%M-%S")
    filename = f"result_{timestamp_str}.csv"
    
    db = self.db_connect()
    cur = db.cursor()

    with open(filename, mode='w', newline='', encoding='utf-8') as csv_file:
        writer = csv.writer(csv_file)           

        cur.execute('select * from "base_cdek_bf"') №
        writer.writerow([desc[0] for desc in cur.description])  
        while True:
            rows = cur.fetchmany(1000)  
            if not rows:
                break
            writer.writerows(rows)
    
    csv_file.close()
    cur.close()
    db.close()

报错信息

cur.execute('select * from "base_cdek_bf"')
psycopg2.errors.InternalError_: could not read block 8810376 in file "base/214899/214911.67": Not enough space

硬件环境

Win10 x64、64GB内存、12核3.6GHz处理器、本地10TB HDD(剩余4TB+),已尝试StringIO()+copy_expert、fetchmany方法均未解决。


问题分析与解决方案

核心问题:报错指向PostgreSQL服务器端磁盘空间不足,而非本地磁盘

报错中的base/214899/214911.67是PostgreSQL服务器端的数据文件路径,这条错误说明服务器端无法读取数据块,因为服务器的磁盘空间不够,和你本地的4TB剩余空间无关。

执行select * from 大表时,PostgreSQL服务器需要在自身磁盘上分配临时空间处理结果集(比如缓存数据、隐含排序操作),180GB的大表会消耗大量服务器端磁盘/内存,这才是报错的根源。

同时代码存在两个语法/冗余问题:

  • cur.execute行末尾的№是无效语法,必须删除
  • csv_file.close()是冗余代码,with open上下文管理器会自动关闭文件

解决方案

  1. 检查并扩容PostgreSQL服务器端磁盘
    登录PostgreSQL服务器,检查数据目录(对应报错里的base/路径)所在磁盘的剩余空间,同时检查临时表空间(temp_tablespaces配置项指定的路径)的磁盘空间,清理冗余文件或直接扩容服务器端磁盘。

  2. 使用PostgreSQL原生COPY命令替代SELECT+fetchmany
    COPY是PostgreSQL专为批量数据导出设计的命令,比Python逐行读取高效得多,且服务器端资源占用更低。正确的Python调用方式如下:

    def save_to_csv(self):
        now = datetime.datetime.now()
        timestamp_str = now.strftime("%Y-%m-%d_%H-%M-%S")
        filename = f"result_{timestamp_str}.csv"
        
        db = self.db_connect()
        cur = db.cursor()
    
        # 用COPY TO STDOUT将服务器端数据流式输出到本地文件
        copy_sql = """COPY "base_cdek_bf" TO STDOUT WITH CSV HEADER ENCODING 'UTF8'"""
        with open(filename, 'w', newline='', encoding='utf-8') as csv_file:
            cur.copy_expert(copy_sql, csv_file)
        
        cur.close()
        db.close()
    

    该方式不会将所有数据加载到Python内存中,而是直接流式写入本地文件,彻底解决内存耗尽问题。

  3. 临时替代方案(无法操作服务器时)
    可以尝试用LIMIT+OFFSET分段导出,但这种方式效率较低,且如果导出过程中表有写入操作,可能出现数据重复/遗漏,仅作为临时应急方案。


内容的提问来源于stack exchange,提问作者Yevhen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 15:55:39