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

使用cx_Oracle与openpyxl导出Excel时遇MemoryError求助

Fixing MemoryError When Exporting 500k Oracle Rows to Excel (Even With write_only=True)

Got it, let’s dig into this MemoryError issue you’re facing. Using write_only=True is a great start, but 500k rows can still sneak up on you if the data flow isn’t optimized. I’ve worked through similar scenarios with large datasets, so here are practical, actionable fixes:


1. Stream Data From Oracle (Don’t Load All Rows at Once)

The most common culprit here is pulling the entire 500k-row result set into memory in one go. Even with write-only Excel mode, if your script holds all rows in RAM before writing, it’ll hit a wall. Instead, use batched fetching to process rows in chunks:

Example with cx_Oracle + openpyxl:

import cx_Oracle
from openpyxl import Workbook

# Configure Oracle connection
conn = cx_Oracle.connect(
    user="your_user",
    password="your_pass",
    dsn="your_host:your_port/your_service"
)

# Set a large arraysize to reduce network trips and control batch size
cursor = conn.cursor(arraysize=10000)
cursor.execute("SELECT col1, col2, col3 FROM your_large_table")  # Avoid SELECT * to skip unused columns!

# Initialize write-only workbook
wb = Workbook(write_only=True)
ws = wb.create_sheet()

# Write header row first
ws.append([desc[0] for desc in cursor.description])

# Process rows in batches
batch_size = 10000
while True:
    rows = cursor.fetchmany(batch_size)
    if not rows:
        break
    # Write each batch to Excel immediately
    for row in rows:
        ws.append(row)
    # Optional: Force flush to free up memory sooner
    ws.flush()

wb.save("large_dataset_export.xlsx")

# Cleanup
cursor.close()
conn.close()

Key notes here:

  • arraysize: Controls how many rows Oracle sends per network call (set to 10k-20k for large datasets).
  • fetchmany(): Pulls only a subset of rows into memory at a time, instead of fetchall().
  • Avoid SELECT *: Only query columns you actually need—extra columns (especially large ones like CLOB/BLOB) bloat memory usage.

2. Handle Large Columns (CLOB/BLOB) Explicitly

If your table contains CLOB or BLOB fields, these can eat up memory fast even in small batches. Modify your query to truncate or exclude them unless necessary:

-- Truncate CLOB to a manageable length if you don't need the full content
SELECT col1, DBMS_LOB.SUBSTR(large_clob_col, 4000) AS truncated_clob FROM your_large_table

3. Switch to 64-bit Python (Critical if You’re on 32-bit)

32-bit Python has a hard memory limit (usually ~2GB), which 500k rows with multiple columns can easily exceed. If you’re running a 32-bit version, upgrading to 64-bit Python will remove this restriction and likely fix the MemoryError immediately.


4. Optimize Excel Library Usage

While openpyxl’s write-only mode is efficient, you can try alternatives like xlsxwriter (which is also designed for large files) if issues persist. Here’s a quick snippet for comparison:

import xlsxwriter

wb = xlsxwriter.Workbook("large_dataset_export.xlsx")
ws = wb.add_worksheet()

# Write header
for col_num, col_name in enumerate(columns):
    ws.write(0, col_num, col_name)

# Write rows in batches
row_num = 1
while True:
    rows = cursor.fetchmany(batch_size)
    if not rows:
        break
    for row in rows:
        for col_num, value in enumerate(row):
            ws.write(row_num, col_num, value)
        row_num += 1

wb.close()

5. Check for Hidden Memory Leaks

Make sure you’re not accidentally holding references to rows after writing them. Avoid storing rows in lists or other data structures—write them to Excel immediately and discard the batch variable.


The core idea here is to keep data flowing in a stream: fetch a chunk, write it, free up memory, repeat. This way, your script never holds more than a small subset of the 500k rows in RAM at once.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 10:16:07