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 表一致,无需特殊处理。
相关推荐
AKAMAI1 分钟前
Akamai 宣布与Anthropic达成 116 亿美元多年期协议,以支持其日益增长的需求
人工智能·云计算
Smoothcloud润云36 分钟前
PyTorch大模型权重加载与启动耗时优化实战:定位磁盘、内存与显存瓶颈
人工智能·pytorch·python·深度学习·gpu算力
databook1 小时前
从循环到向量化:NumPy提速的7个关键思维
python·数据分析·numpy
别动我齐刘海1 小时前
Linux 系统调试学习1
linux·运维·服务器·c++·学习·机器学习·机器人
棉猴1 小时前
玩游戏学Python1-Python和pgzero库的安装
python·pygame·玩游戏·pgzero·pgzrun
诺伦2 小时前
GEO优化数据实证:78%引用流向官网的机制拆解与小品牌三步管线实战教程 | RiseClaw玄策
python·seo·geo·内容营销·ai搜索
oooost2 小时前
pytorch学习笔记1
python·学习方法
数字融合2 小时前
透明化视频孪生虚实映射一体化融合技术
人工智能·python·数码相机
不像程序员的程序媛3 小时前
linux常见文本操作命令
linux·运维·服务器
jack186893 小时前
Lovable.Dev 全栈应用快速落地实战指南
python