FastAPI返回大量JSON数据速度极慢,寻求高效优化方案
优化FastAPI返回大量Parquet数据的性能方案
你的核心问题在于冗余的JSON序列化/反序列化步骤,以及低效的客户端侧数据筛选,以下是针对性的优化方案:
1. 移除冗余的JSON转换环节
原parse_parquet函数把DataFrame转成JSON字符串再解析为Python列表,这两步完全多余,直接返回DataFrame就能省去大量时间:
def parse_parquet(file_path): # 直接返回Pandas DataFrame,跳过JSON序列化/反序列化 return pd.read_parquet(file_path)
2. 在Pandas层面对数据提前筛选
不要把全量数据加载为Python列表后再用列表推导筛选,Pandas的向量化操作比Python循环快几个数量级,直接在DataFrame阶段完成筛选:
@app.get('/endpoint') async def some_function(year: int | None = None, id: str | None = None): # 修正原逻辑错误:year有值时加载对应年份文件,无值时加载全量数据 if year is not None: df = parse_parquet(f'path/{year}_data.parquet') else: df = parse_parquet(f'path/all_data.parquet') # 用Pandas布尔索引筛选数据,替代列表推导 if id is not None: df = df[df['id'] == id]
3. 高效序列化并流式返回数据
直接返回DataFrame时,FastAPI默认用标准json模块序列化,速度较慢。改用更高效的方式返回JSON字符串,同时启用流式传输避免内存过载:
方案A:用Pandas直接生成JSON字符串并流式返回
from fastapi.responses import StreamingResponse @app.get('/endpoint') async def some_function(year: int | None = None, id: str | None = None): # 同上的文件读取和筛选逻辑 if year is not None: df = parse_parquet(f'path/{year}_data.parquet') else: df = parse_parquet(f'path/all_data.parquet') if id is not None: df = df[df['id'] == id] # 生成JSON字符串并通过流式响应返回 json_data = df.to_json(orient='records') return StreamingResponse(iter([json_data]), media_type='application/json')
方案B:使用更快的JSON库(如orjson)加速序列化
安装orjson后,用它替代默认的JSON序列化工具,速度能提升数倍:
pip install orjson
修改代码:
from fastapi.responses import StreamingResponse import orjson @app.get('/endpoint') async def some_function(year: int | None = None, id: str | None = None): # 文件读取和筛选逻辑同上 # 用orjson序列化DataFrame数据 json_data = orjson.dumps(df.to_dict(orient='records'), option=orjson.OPT_INDENT_2) return StreamingResponse(iter([json_data]), media_type='application/json')
关键优化效果说明
- 移除冗余的JSON转解析步骤:直接减少两次全量数据的序列化/反序列化开销
- Pandas向量化筛选:比Python列表推导快10~100倍,数据量越大优势越明显
- 高效JSON库+流式传输:进一步降低序列化时间,同时避免大内存占用
内容的提问来源于stack exchange,提问作者codeweird
相关产品推荐
相关产品推荐

