Databricks里用PySpark统计指定表和字段中各字段的空值、空字符串或零值比例

python 复制代码
from pyspark.sql import SparkSession
from pyspark.sql.functions import col, coalesce, trim, when, lit, sum
from pyspark.sql.types import StringType, NumericType

# 在 Databricks 中,spark 会话通常已经存在,无需重新创建
# 如果需要显式创建,使用:
# spark = SparkSession.builder.getOrCreate()

# 配置参数
database_name = "your_database"  # 替换为实际数据库名
result_list = []

# 获取数据库中的所有表和视图(包括 Delta 表)
tables = spark.catalog.listTables(database_name)

for table in tables:
    table_name = table.name
    full_table_name = f"{database_name}.{table_name}"
    
    try:
        # 读取表或视图(Delta 表和普通表均可)
        df = spark.table(full_table_name)
        
        # 快速判断是否为空表,避免不必要的缓存
        total_count = df.count()
        if total_count == 0:
            continue
        
        # 缓存数据以便多次引用(实际上我们只需扫描一次,缓存并非必需)
        df.cache()
        
        # 构建所有字段的聚合表达式(一次性计算)
        agg_exprs = []
        field_meta = []  # 用于记录每个字段的类型和名称
        
        for field in df.schema.fields:
            col_name = field.name
            col_type = field.dataType
            
            if isinstance(col_type, StringType):
                # 字符串类型:统计 null 或 trim 后为空字符串
                modified_col = trim(coalesce(col(col_name), lit("")))
                condition = (modified_col == lit(""))
                count_expr = sum(when(condition, 1).otherwise(0)).alias(f"cnt_{col_name}")
            elif isinstance(col_type, NumericType):
                # 数值类型:统计 null 或零值
                modified_col = coalesce(col(col_name), lit(0))
                condition = (modified_col == lit(0))
                count_expr = sum(when(condition, 1).otherwise(0)).alias(f"cnt_{col_name}")
            else:
                # 其他类型:仅统计 null
                condition = col(col_name).isNull()
                count_expr = sum(when(condition, 1).otherwise(0)).alias(f"cnt_{col_name}")
            
            agg_exprs.append(count_expr)
            field_meta.append((col_name, str(col_type)))
        
        # 执行一次聚合,获取所有字段的统计值
        stats_row = df.agg(*agg_exprs).collect()[0]
        
        # 整理结果
        for col_name, col_type in field_meta:
            stat_count = stats_row[f"cnt_{col_name}"]
            percentage = round((stat_count / total_count) * 100, 2) if total_count > 0 else 0.0
            result_list.append((
                database_name,
                table_name,
                col_name,
                col_type,
                stat_count,
                total_count,
                float(percentage)
            ))
        
        df.unpersist()  # 释放缓存
        
    except Exception as e:
        print(f"Error processing table {table_name}: {str(e)}")
        continue

# 创建结果 DataFrame
result_columns = [
    "database_name",
    "table_name",
    "column_name",
    "column_type",
    "stat_count",
    "total_rows",
    "percentage"
]

result_df = spark.createDataFrame(result_list, result_columns)

# 显示结果
result_df.show(truncate=False)

# 可选:将结果保存到 Delta 表
# result_df.write.format("delta").mode("overwrite").saveAsTable("your_audit_table")

主要改动说明

原代码 修改后 原因
显式创建 SparkSession 并启用 Hive 直接使用 Databricks 内置 spark Databricks 已预配置,无需额外初始化
对每个字段分别执行 df.agg() 构建所有字段聚合表达式,一次 df.agg() 减少表扫描次数,大幅提高性能
缓存 df 后多次扫描 缓存后仅一次聚合扫描 配合优化,降低缓存开销
spark.catalog.listTables() 同样使用,能返回表和视图 无需修改,原生支持 Delta 表和视图
异常处理与结果收集 保持不变 逻辑通用

注意事项

  • 数据库名称 :根据实际环境修改 database_name,如果使用默认数据库,可设为 "default"
  • 视图spark.table() 可以读取持久化视图,但临时视图不会出现在 listTables 中。如需处理临时视图,可额外指定名称列表。
  • 性能 :对于大型表,df.count() 和聚合仍会触发一次完整扫描,这是必要的。如果表极大,可考虑分批处理或使用抽样估算。
  • Delta 表:Delta 表在 Catalog 中通常显示为普通表名,读取方式与 Hive 表一致,无需特殊处理。
相关推荐
躺不平的理查德22 分钟前
Nginx与Ajax 备忘录
linux·运维·服务器
海兰23 分钟前
【 Python 量化交易】第6章:数据可视化
开发语言·python·信息可视化
多多鼠24 分钟前
Tool Calling的信任边界:从协议校验到执行沙箱的完整链路设计
运维·开发语言·网络·人工智能·python·langchain
Neighbor_OldY37 分钟前
【实战复盘】RDP暴力破解与内网横向移动溯源:Windows全套排查命令与事件ID硬核解析
运维·windows·web安全
项目管理实用笔记38 分钟前
CI/CD是什么?持续集成持续交付入门
运维·ci/cd·研发效能·项目管理·团队开发
Sunqk566539 分钟前
将开发板串口连接到Ubuntu后未找到对应的设备文件?
linux·运维·ubuntu
Jazz_z40 分钟前
使用 Python 合并与取消合并 Excel 单元格
开发语言·python·excel
Lenyiin41 分钟前
第6篇_Python高级语法与标准库精髓:从会用到达精通
java·python·html
淼澄研学42 分钟前
Debian通过AI决议:合规解析与Ollama本地部署Llama3实操
运维·人工智能·debian