Python使用正则表达式批量标准化运营商数据的性能优化问题
运营商正则批量清洗优化方案
原始代码运行效率低的核心问题:
- 采用两层嵌套循环,时间复杂度为
O(待清洗运营商数量*2000规则数),数据量稍大就会出现明显卡顿 - 没有预编译正则表达式,每次匹配都要临时解析正则规则,额外消耗大量性能
- 使用pandas的
iterrows方法遍历数据,本身比向量化操作慢2-3个数量级 - 未对重复的原始运营商名称做去重处理,重复执行完全相同的匹配逻辑
优化步骤
- 预编译所有正则规则:提前把SQL中读取的2000条正则全部编译完成,同时绑定对应的标准化运营商名称,避免每次匹配重复编译
- 原始运营商去重处理:先提取所有唯一的待清洗运营商名称完成匹配,再通过映射关系批量回写到全量数据,大幅减少匹配次数
- 用向量化操作替代循环:用pandas的映射方法替代
iterrows遍历,减少Python层循环开销 - 可选优化:如果规则之间没有优先级冲突,可以把所有正则合并为一个带捕获组的组合正则,单次扫描即可完成匹配,将时间复杂度降到
O(待清洗运营商数量)
优化后代码示例
import sys import re import pyodbc import pandas as pd rpt_id = 1234 # rpt_id = sys.argv[1] # 数据库连接 try: conn = pyodbc.connect('Driver={SQL Server};' 'Server=xxxxxxxxx;' 'Database=xxxxxxxxx;' 'Trusted_Connection=xxxxx;') except: print('Connection Failed') sys.exit() # 预处理待清洗数据 with conn.cursor() as cursor: cursor.execute(f"delete from [dbo].[python_test1] where rpt_id = '{rpt_id}'") conn.commit() cursor.execute(f"insert into [dbo].[python_test1](rpt_id, raw_carr_nm) select distinct rpt_id, raw_carr_nm from [dbo].[wrk_data] where rpt_id = '{rpt_id}'") conn.commit() # 1. 读取正则规则并预编译,可根据需求调整匹配 flags(比如是否忽略大小写) regex_df = pd.read_sql("SELECT [raw_pattern], [Carrier] FROM [dbo].[ref_regex_t]", conn) compiled_rules = [ (re.compile(pattern), standard_name) for pattern, standard_name in zip(regex_df['raw_pattern'], regex_df['Carrier']) ] # 2. 读取待清洗的运营商数据 carriers_df = pd.read_sql(f"select * from [dbo].[python_test1] where rpt_id = '{rpt_id}'", conn) # 3. 去重待匹配的原始运营商名称,减少重复匹配次数 unique_raw_carriers = carriers_df['raw_carr_nm'].unique() match_map = {} # 4. 仅对唯一值做匹配 for raw_carrier in unique_raw_carriers: matched_name = raw_carrier # 无匹配默认保留原始值 for pattern, standard_name in compiled_rules: if pattern.match(raw_carrier): # 用match还是search可根据业务需求调整 matched_name = standard_name break # 匹配到第一条规则就退出,可按规则优先级调整顺序 match_map[raw_carrier] = matched_name # 5. 批量映射回全量数据 carriers_df['standard_carrier'] = carriers_df['raw_carr_nm'].map(match_map) # 此处可添加结果写入数据库的逻辑,省略 print(carriers_df) conn.close()
注意:上述代码中直接拼接SQL字符串存在注入风险,生产环境建议改用参数化查询
额外性能提升建议
- 如果规则有明确匹配优先级,把高频命中的规则放到规则列表最前面,减少无效遍历次数
- 如果正则都是全匹配规则,可以直接用字典映射替代正则匹配,性能会提升上百倍
- 待清洗数据量超过10万条的话,可以考虑用多进程并行处理匹配逻辑,充分利用CPU核心
内容的提问来源于stack exchange,提问作者William Barnes
相关产品推荐
相关产品推荐

