Python中如何加快exchangelib QuerySet对象转JSON数组的速度
原因说明
原代码耗时高的核心原因有两个:
- exchangelib的QuerySet默认是分页懒加载,遍历过程中会逐页发起网络请求拉取数据,默认页大小仅为100条,15万条需要发起1500次网络请求,耗时极高
- 逐个实例化ORM对象、手动拼接字典的操作,对15万级数据量来说本身开销就非常大
优化方案
方案1:直接使用values()方法批量获取字典(最优,可达到秒级转换)
exchangelib的QuerySet原生支持values()方法,不需要遍历ORM实例对象,直接返回符合要求的字典列表,既避免了实例化的高额开销,也不会触发额外的延迟加载请求,是性能最高的方案。
query_filter = Q(sender="xyz@abc.com") timeLimit = UTC_NOW() - timedelta(hours=1) # 直接通过values指定返回字段的映射关系,支持双下划线取关联属性 MailsArray = list(account.inbox.all().filter( query_filter, datetime_received__gt=timeLimit ).values( Subject="subject", ID="conversation_id__id" ))
如果需要输出JSON字符串,直接对结果调用json.dumps(MailsArray)即可。
方案2:调整分页大小+列表推导式处理(适用于有自定义处理逻辑的场景)
如果有values()无法满足的自定义处理逻辑,可以先调整分页大小一次性拉取全量数据到本地,再用列表推导式替代普通for循环,性能提升至少5~10倍。
query_filter = Q(sender="xyz@abc.com") timeLimit = UTC_NOW() - timedelta(hours=1) # 调整page_size大于结果集总量,一次性拉取所有数据,避免多次网络请求 Inbox_mails = list(account.inbox.all().filter( query_filter, datetime_received__gt=timeLimit ).only('subject','conversation_id').page_size(200000)) # 列表推导式比for循环append效率高很多 MailsArray = [{"Subject":x.subject, "ID":x.conversation_id.id} for x in Inbox_mails]
注意事项
- 不要在遍历过程中访问没有在
only()/values()里声明的字段,否则会触发单条数据的延迟查询,大幅增加耗时 - 15万条数据的JSON序列化可以直接用标准库
json模块,如果需要更快的速度可以安装使用ujson替代标准库json
内容的提问来源于stack exchange,提问作者gow_r
相关产品推荐
相关产品推荐

