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

使用openpyxl匹配大小Excel表数据时如何优化过长运行时长?

性能问题根源

你当前的代码采用嵌套循环逻辑,时间复杂度为O(N*M),其中N是表格1的2万行,M是表格2的100万行,总运算量达到200亿次,必然会出现运行时间过长的问题。

最优优化方案:哈希字典查找

该方案时间复杂度为O(N+M),实现简单且查询效率比二分查找更高,是这类匹配场景的首选方案。
核心逻辑是先遍历一次表格2,将ID作为key、对应行数据作为value存入字典,后续遍历表格1时直接做O(1)的哈希查询即可。
实现代码如下:

import openpyxl
import csv

# 1. 预加载表格2构建ID映射字典
g2 = openpyxl.load_workbook('path/to/sheet2/sheet2.xlsx', read_only=True)
grid2 = g2.active
id_to_row = {}

# 如果表格2有表头,可加下一行跳过表头
# next(grid2.rows)
for row in grid2.rows:
    id_val = row[0].value
    if id_val is None:
        continue
    try:
        id_key = int(id_val)
        # 提前处理好行内容,避免后续重复计算
        row_content = [str(c.value) for c in row[1:]]
        id_to_row[id_key] = row_content
    except (ValueError, TypeError):
        continue
g2.close()

# 2. 遍历表格1匹配写入结果
g1 = openpyxl.load_workbook('path/to/sheet/sheet1.xlsx', read_only=True)
grid1 = g1.active

with open('output.csv', 'w', encoding='utf-8', newline='') as f:
    writer = csv.writer(f)
    # 如果表格1有表头,可加下一行跳过表头
    # next(grid1.rows)
    for row in grid1.rows:
        match_val = row[1].value
        output_key = row[0].value
        if match_val is None or output_key is None:
            continue
        try:
            search_key = int(match_val)
            if search_key in id_to_row:
                writer.writerow([str(int(output_key))] + id_to_row[search_key])
        except (ValueError, TypeError):
            continue
g1.close()

100万行的表格2数据完全可以正常存入内存,整个流程运行时间通常在分钟级甚至秒级。

二分查找实现方案(次选)

如果你需要按照指定的二分查找方案实现,需要注意该方案要求表格2的ID列有序,如果原表ID无序需要先做排序,整体时间复杂度为O(M logM + N logM),性能略低于哈希方案。
实现代码如下:

import openpyxl
import csv
import bisect

# 1. 加载表格2数据
g2 = openpyxl.load_workbook('path/to/sheet2/sheet2.xlsx', read_only=True)
grid2 = g2.active
id_row_list = []

# next(grid2.rows) # 有表头则取消注释
for row in grid2.rows:
    id_val = row[0].value
    if id_val is None:
        continue
    try:
        id_key = int(id_val)
        row_content = [str(c.value) for c in row[1:]]
        id_row_list.append((id_key, row_content))
    except:
        continue
g2.close()

# 2. 按ID排序(如果原表ID已经有序可以跳过这一步)
id_row_list.sort(key=lambda x: x[0])
id_list = [item[0] for item in id_row_list]

# 3. 遍历表格1二分查找匹配
g1 = openpyxl.load_workbook('path/to/sheet/sheet1.xlsx', read_only=True)
grid1 = g1.active

with open('output.csv', 'w', encoding='utf-8', newline='') as f:
    writer = csv.writer(f)
    # next(grid1.rows) # 有表头则取消注释
    for row in grid1.rows:
        match_val = row[1].value
        output_key = row[0].value
        if match_val is None or output_key is None:
            continue
        try:
            search_key = int(match_val)
            idx = bisect.bisect_left(id_list, search_key)
            if idx < len(id_list) and id_list[idx] == search_key:
                writer.writerow([str(int(output_key))] + id_row_list[idx][1])
        except:
            continue
g1.close()
额外优化建议
  • 大体积Excel文件读写优先用pandas、polars这类结构化数据处理库,比openpyxl性能高3-10倍,且匹配逻辑更简洁,pandas实现参考代码:
import pandas as pd

# 读取两个表格
df1 = pd.read_excel('path/to/sheet1.xlsx', usecols=[0,1], names=['output_key', 'match_id'])
df2 = pd.read_excel('path/to/sheet2.xlsx')
# 关联匹配
result = df1.merge(df2, left_on='match_id', right_on='ID', how='inner')
# 输出结果
result.to_csv('output.csv', index=False, encoding='utf-8')
  • 删掉所有不必要的print语句,打印操作会大幅拖慢执行速度。
  • 如果存在同一ID对应多行的场景,哈希方案中可以把字典的value改成列表,存储所有匹配的行即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 09:15:01