Python一些可能用的到的函数系列110 按自增id自动切块运行

本文探讨了Python在处理大量数据时遇到的内存膨胀和效率问题,通过实例展示了如何使用分块技术处理一亿条数据库ID,以避免性能瓶颈并优化内存使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

说明

Python还是有其自身局限的

我觉得python的一些对象设计应该有一些缺陷(没有验证),至少我碰到了几种情况,导致了内存膨胀,或者处理速度非常慢:

  • 1 list。 当list对象里面的元素过多时,处理会非常慢,时间的延长不是线性的,而是指数的
  • 2 request。本次我一次请求数据库中约一亿条数据的id时,内存直接膨胀超限。id本身很小,后续使用分块方式读出时,python程序和数据库占用内存不过5G, 而一次请求时数据时,内存膨胀超过70G还没有停止。

内容

使用一个通用程序来分块执行任务

# 1 根据最大最小id制作tuple list
def slice_list_by_batch1(min_idx, max_idx, batch_num):
    batch_list =list(range(min_idx, max_idx + batch_num , batch_num))
    res_list = []
    for i in range(len(batch_list)-1):
        res_list.append((batch_list[i],batch_list[i+1]))
    return res_list

# 2 运行的封装

import tqdm
import pandas as pd
# 按照区块进行处理 | 注意,区块的数量最好不要超过1万个, Mongo建议以10万每次的数据读取;Mysql以每次1万条读取。
def process_by_blocks(min_idx, max_idx, batch_num , partial_block_process):
    id_tuple_list = slice_list_by_batch1(min_idx, max_idx, batch_num)
    df_list = []
    fail_tuple_list = []
    
    for id_tuple in tqdm.tqdm(id_tuple_list):
        try:
            tem_df = partial_block_process(id_tuple = id_tuple)
            df_list.append(tem_df)
        except:
            fail_tuple_list.append(id_tuple)
    
    print('Successful Blocks:' , len(df_list))
    print('Fail Blocks:' , len(fail_tuple_list))
    
    res_dict = {}
    res_dict['data'] = pd.concat(df_list, ignore_index=True)
    res_dict['fail_tuples'] =  fail_tuple_list
    return res_dict

# 3 具体的处理逻辑
import requests as req
import pandas as pd 
mongo_agent_host = 'http://172.17.0.1:24011/'
def block_process(id_tuple = None, id_name = None, keep_cols = None):
    start_id, end_id = id_tuple
    start_id = int(start_id)
    end_id = int(end_id)
    limits = end_id - start_id + 1 
    task_id_series_data = req.post(mongo_agent_host+ 'query_recs_v2/', json = {'connection_hash':'61c73a1cacd7b216e71dcdb7c8f56f5f', 
                                                                                'filter_dict':{id_name : {'$gte':start_id, '$lt':end_id}},
                                                                                'tier1':'xs','tier2':'ktggcn_raw',
                                                                                 'keep_cols' : keep_cols,
                                                                               'limits':limits
                                                                               }).json()
    if task_id_series_data['status']:
        if len(task_id_series_data['data']):
            return pd.DataFrame(task_id_series_data['data'])
        else:
            return pd.DataFrame()
    else:
        raise Exception('请求失败', id_tuple)

具体的执行

id_min = 13220001
id_max = 98340000

from functools import partial
block_process_1 = partial(block_process, id_name='task_id', keep_cols=['task_id'])
task_id_series = process_by_blocks(id_min,id_max, 100000,  block_process_1)

100%|██████████| 852/852 [05:15<00:00,  2.70it/s]
Successful Blocks: 852
Fail Blocks: 0

指定一个具体的处理逻辑,只要输入起始和终止id就可以进行任务,要用的时候进行偏置就可以了。

大约5分钟读取了一亿的数据,可以直接进行分析。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值