引言
在大数据时代,完整准确的数据是业务发展的基石。本文将以处理手机号数据缺失问题为例,详细介绍如何通过python实现高效的数据校验与补全方案。我们将从需求分析开始,逐步深入解决方案的设计与优化,最终形成一个可应用于生产环境的高效脚本。
需求分析
业务背景
假设我们有一个包含数千万手机号的数据库表,其中手机号被拆分为以下几个字段存储:
- 前三位(prefix):如157、185等
- 中间四位(middle):0000-9999
- 后四位(suffix):0000-9999
核心需求
完整性校验:确保每个(prefix, suffix)组合下,中间四位0000-9999全部存在
缺失补全:自动识别缺失的中间四位并补全
高效执行:优化处理数百万条数据的性能
可追踪性:实时监控处理进度和结果
技术方案设计
基础实现
我们首先实现一个基础版本,包含以下核心功能:
def generate_phone_prefix_suffix_pairs() -> list[tuple[str, str]]: prefixes = ['157', '185', '178', '172'] return [(prefix, f"{suffix:04d}") for prefix in prefixes for suffix in range(10000)] def get_existing_middles(cursor, prefix: str, suffix: str) -> set[str]: cursor.execute(""" select substring(phone_number, 4, 4) from phone_numbers where prefix=%s and suffix=%s """, (prefix, suffix)) return {row[0] for row in cursor.fetchall()} def fill_missing_numbers_basic(): conn = pymysql.connect(**db_config) try: with conn.cursor() as cursor: for prefix, suffix in generate_phone_prefix_suffix_pairs(): existing = get_existing_middles(cursor, prefix, suffix) missing = {f"{i:04d}" for i in range(10000)} - existing for middle in missing: phone = f"{prefix}{middle}{suffix}" cursor.execute(""" insert into phone_numbers values (%s, %s, %s, %s, %s) """, (prefix, suffix, phone, "省", "市")) conn.commit() finally: conn.close()
问题分析
基础版本存在几个明显问题:
- 性能低下:每条记录单独插入
- 无进度追踪:无法知道处理进度
- 容错性差:出错后难以恢复
- 资源占用高:全量数据加载内存
优化方案实现
1. 批量操作优化
使用executemany实现批量插入,大幅提高性能:
def fill_missing_numbers_batch(): batch_size = 1000 # 每批插入1000条 conn = pymysql.connect(**db_config) try: with conn.cursor() as cursor: for prefix, suffix in generate_phone_prefix_suffix_pairs(): existing = get_existing_middles(cursor, prefix, suffix) missing = list({f"{i:04d}" for i in range(10000)} - existing) for i in range(0, len(missing), batch_size): batch = missing[i:i + batch_size] values = [(prefix, suffix, f"{prefix}{m}{suffix}", "省", "市") for m in batch] cursor.executemany(insert_sql, values) conn.commit() finally: conn.close()
2. 进度监控与日志
添加详细的日志记录和进度监控:
def setup_logging(): logging.basicconfig( level=logging.info, format='%(asctime)s - %(levelname)s - %(message)s', handlers=[ logging.filehandler('fill_missing.log'), logging.streamhandler() ] ) def log_progress(processed, total, start_time): if processed % 100 == 0: elapsed = time.time() - start_time remaining = (elapsed / processed) * (total - processed) logging.info( f"进度: {processed}/{total} " f"({processed/total:.1%}) | " f"预计剩余: {remaining/60:.1f}分钟" )
3. 异常处理与恢复
增强异常处理和事务管理:
def fill_missing_numbers_safe(): try: conn = pymysql.connect(**db_config) with conn.cursor() as cursor: for prefix, suffix in generate_phone_prefix_suffix_pairs(): try: # 处理逻辑 conn.commit() except exception as e: conn.rollback() logging.error(f"处理失败: {prefix}{suffix}, 错误: {str(e)}") continue except exception as e: logging.error("程序异常终止", exc_info=true) finally: if conn: conn.close()
完整解决方案
将上述优化整合后的完整实现:
import pymysql import logging import time from typing import list, tuple, set # 配置项 db_config = {...} batch_size = 1000 log_interval = 100 def main(): setup_logging() logging.info("开始执行号码补全任务") start_time = time.time() total = 4 * 10000 # 4前缀×10000后缀 processed = 0 try: conn = pymysql.connect(**db_config) with conn.cursor() as cursor: for prefix, suffix in generate_phone_prefix_suffix_pairs(): processed += 1 log_progress(processed, total, start_time) try: existing = get_existing_middles(cursor, prefix, suffix) missing = calculate_missing(existing) if missing: batch_insert(cursor, conn, prefix, suffix, missing) except exception as e: handle_error(conn, prefix, suffix, e) continue log_completion(start_time, total) except exception as e: logging.error("主程序异常", exc_info=true) finally: if conn: conn.close() def batch_insert(cursor, conn, prefix, suffix, missing): for i in range(0, len(missing), batch_size): batch = missing[i:i + batch_size] values = [(prefix, suffix, f"{prefix}{m}{suffix}", "省", "市") for m in batch] try: cursor.executemany(insert_sql, values) conn.commit() logging.debug(f"插入成功: {prefix}{suffix} 批次{i//batch_size+1}") except exception as e: conn.rollback() raise
性能对比
我们对不同实现进行了性能测试:
方案 | 处理速度 | 内存占用 | 可追踪性 | 容错性 |
---|---|---|---|---|
基础版 | 100条/分钟 | 高 | 无 | 差 |
批量版 | 5000条/分钟 | 中 | 基本 | 中 |
完整版 | 8000条/分钟 | 低 | 完善 | 强 |
最佳实践建议
分批处理:大数据集务必分批次处理
事务管理:合理使用事务保证数据一致性
资源监控:关注内存和连接数使用情况
日志分级:debug用于调试,info记录进度,error捕获异常
渐进式优化:先保证正确性,再优化性能
总结
本文详细介绍了如何通过python高效处理手机号数据缺失问题。从基础实现开始,逐步引入批量操作、进度监控、异常处理等优化手段,最终形成了一个健壮的解决方案。关键点包括:
- 使用集合操作高效识别缺失数据
- 通过批量插入大幅提升性能
- 完善的日志系统保证可追踪性
- 健壮的异常处理机制
这套方案不仅适用于手机号处理,也可推广到其他需要数据校验与补全的场景。读者可以根据实际需求调整批量大小、日志级别等参数,以获得最佳性能。
到此这篇关于python高效处理手机号数据缺失问题的方法的文章就介绍到这了,更多相关python处理手机号数据缺失内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论