Geopandas高效读取GeoPackage分片:如何分块读取gpkg降低内存峰值
高效分块读取GPKG文件的两种可行方案
方案1:使用pyogrio原生分块能力(推荐)
当前版本的geopandas底层依赖的矢量IO库pyogrio已经原生支持类似pandas的分块读取能力,底层会保持文件连接,不会重复扫描全文件,性能损耗极低,是最优解。
你可以直接通过geopandas.read_file的batch_size参数(geopandas 0.12版本及以上支持)获取分块迭代器:
import geopandas as gpd # 定义每个分块的行数 CHUNK_SIZE = 10000 # 直接迭代分块,不需要手动维护起止位置 for chunk in gpd.read_file("data.gpkg", batch_size=CHUNK_SIZE): # 此处编写当前分块的处理逻辑 print(f"当前分块行数:{len(chunk)}")
如果你的geopandas版本较低,也可以直接调用pyogrio的接口实现:
from pyogrio import read_dataframe for chunk in read_dataframe("data.gpkg", batch_size=10000): # 处理分块 pass
如果运行提示找不到pyogrio,可通过pip install pyogrio或者conda install pyogrio安装,geopandas会自动优先使用该后端做矢量文件读写,相比传统fiona后端性能有3~10倍提升。
方案2:基于GPKG的SQLite特性分页查询
GPKG格式本质是SQLite数据库的衍生格式,你可以直接通过SQL语句的LIMIT + OFFSET语法实现分页读取,性能远高于之前使用slice参数的实现:
import geopandas as gpd # 先读取元数据获取总数据量,该操作不会加载实际行,耗时极短 total_rows = len(gpd.read_file("data.gpkg", rows=0)) CHUNK_SIZE = 10000 # 分页读取 for offset in range(0, total_rows, CHUNK_SIZE): # 替换sql语句中的“图层名”为你的gpkg里实际存储的图层名称 sql = f"SELECT * FROM 图层名 LIMIT {CHUNK_SIZE} OFFSET {offset}" chunk = gpd.read_file("data.gpkg", sql=sql) # 处理当前分块
补充说明
之前使用slice参数读取越靠后的分块越慢,是因为传统fiona后端的行切片实现逻辑是从文件第一行开始扫描,直到扫完你指定的结束行位置,所以末尾分片相当于每次都要扫描全文件,耗时自然会成倍增长,上述两种方案都避免了这个问题。
另外你可以在读取时通过columns参数指定仅读取需要的字段,进一步降低内存占用和IO耗时。
内容的提问来源于stack exchange,提问作者Stephen
相关产品推荐
相关产品推荐

