1. 项目概述:为什么数据验证不再是“可选项”,而是上线前的硬性关卡
在我们团队去年交付的7个中型数据分析项目里,有4个在UAT阶段被业务方打回,原因不是模型不准、不是报表不美观,而是——
上游数据字段突然多了一列空格、时间格式从ISO8601变成了毫秒时间戳、某个关键枚举值悄悄新增了“待确认”状态
。这些变化本身微小,但直接导致下游ETL任务报错、BI看板指标归零、甚至触发错误告警。当时我们花3天时间定位问题,2天写临时清洗脚本,最后1天紧急发布补丁。而真正该花时间的地方——比如优化特征工程、提升模型泛化能力——全被拖住了。这件事让我彻底意识到:
数据质量不是数据工程师的“附加题”,而是整个数据链路的“起始线”。
这就是我决定系统梳理
Great Expectations
(GE)的核心动因。它不是一个花哨的可视化工具,而是一套用Python代码定义、可版本控制、能嵌入CI/CD的数据契约(Data Contract)。你不需要把它理解成“又一个数据监控平台”,更准确地说,它是
给数据加上的第一道单元测试
——就像你不会在没跑通
test_calculate_revenue()
之前就合并Python代码一样,你不该在没通过
expect_column_values_to_not_be_null("order_id")
之前就把数据表推到生产环境。这篇教程完全基于我在金融风控和电商用户行为两个真实场景中的落地经验,不讲抽象概念,只拆解“怎么写第一条期望(Expectation)”、“怎么让校验结果自动阻断Airflow DAG”、“怎么把几百条规则收敛成可维护的YAML模板”。如果你正在被“数据一变,全链路崩”的问题困扰,或者刚接手一个没人敢动的“祖传数仓”,那接下来的内容,就是你明天就能抄作业的实操手册。
2. 核心设计逻辑:为什么GE不是另一个Pandas校验库,而是数据治理的基础设施级选择
2.1 从“事后救火”到“事前契约”:GE解决的根本矛盾
很多团队初期尝试数据验证时,会直接用Pandas写一堆
df["col"].isnull().sum() > 0
这样的检查脚本。这看似简单,但很快会陷入三个死循环:第一,脚本散落在各个notebook里,没人知道哪份是最新版;第二,校验逻辑和业务逻辑耦合,改一个字段类型就得同步改十几处校验;第三,校验结果只是打印在日志里,没人看,更没人管。GE的设计哲学恰恰是反其道而行之——它强制你把数据质量要求
显式声明
出来,并赋予其和代码同等的地位。举个最典型的例子:在我们的用户注册表中,“手机号”字段必须满足中国11位手机号正则、且不能为虚拟号段(如170、171开头)。用传统方式,你可能在ETL脚本里写
re.match(r"^1[3-9]\d{9}$", phone)
,但如果这个规则未来要扩展“排除已注销号码库”,你就得去翻所有ETL脚本。而GE的做法是:在
expectations.yaml
里定义一条规则:
- expectation_type: expect_column_values_to_match_regex
kwargs:
column: phone_number
regex: ^1[3-9]\d{9}$
mostly: 0.999
这条规则本身不执行任何清洗,它只回答一个问题:“当前这批数据,是否符合我们约定的质量标准?”答案是布尔值(True/False),可以被任何系统消费。这才是基础设施级思维—— 把质量要求从代码里抽离,变成可独立管理、可版本比对、可跨团队对齐的“数据契约” 。我见过最震撼的实践是在某银行项目中,他们把GE的期望配置文件和数据库DDL一起纳入Git仓库,每次表结构变更PR,都必须同步更新对应的期望规则,否则CI流水线直接失败。这种机制倒逼数据产品经理、开发、测试三方在需求评审阶段就必须对齐“手机号字段的业务含义和质量边界”,而不是等上线后互相甩锅。
2.2 GE的三层架构:为什么它能同时满足开发者、数据工程师和业务方的需求
GE的架构设计非常精妙,它用三层抽象解决了不同角色的关注点冲突:
-
第一层:Expectation(期望) —— 这是最小的原子单元,对应具体的数据质量规则。比如
expect_table_row_count_to_equal(1000)或expect_column_mean_to_be_between("revenue", min_value=100, max_value=5000)。它的价值在于 可组合、可复用 。我们不会为每个报表单独写一套校验,而是构建了一个内部期望库:finance_expectations.py里封装了expect_revenue_positive(),expect_date_in_fiscal_quarter()等方法,其他项目直接导入调用。这避免了规则重复定义,也保证了全公司财务类指标的校验口径绝对一致。 -
第二层:Checkpoint(检查点) —— 这是GE的“执行引擎”。它把一批相关联的Expectation、数据源(如PostgreSQL连接)、评估参数(如只校验最近7天数据)打包成一个可调度的任务。关键点在于: Checkpoint不是一次性脚本,而是可配置、可重试、可审计的实体 。我们在Airflow中创建了一个
ge_checkpoint_operator,它接收Checkpoint名称作为参数,自动拉取对应配置、执行校验、将结果写入DataDocs(GE的静态报告站点)并返回状态码。当某次调度失败时,运维人员不用登录服务器查日志,直接打开DataDocs链接,就能看到是哪条规则失败、失败了多少行、样本数据是什么——这是传统脚本完全做不到的透明度。 -
第三层:Data Context(数据上下文) —— 这是GE的“中枢神经系统”。它管理所有配置:数据源连接信息(存于
great_expectations.yml)、期望存储位置(默认是本地uncommitted/expectations/目录)、DataDocs生成路径、甚至插件配置。它的核心价值是 环境隔离与配置即代码 。我们在开发、测试、生产环境分别维护三套great_expectations/目录,通过环境变量GE_ENV=prod动态加载。这样,开发人员在本地运行ge checkpoint run sales_daily时,连接的是测试库;而生产DAG调度时,自动切换到生产库。所有配置都走Git,杜绝了“配置漂移”(Configuration Drift)问题——这是我们在某客户现场踩过最深的坑:他们的测试环境校验通过,但生产环境因为连接池配置不同,导致GE扫描超时,整个数据管道被阻塞了12小时。
2.3 为什么GE不依赖Spark或Dask?轻量级设计背后的务实考量
经常有朋友问:“GE能处理PB级数据吗?要不要集成Spark?”我的回答很直接:
GE的定位从来不是大数据计算引擎,而是质量门禁(Quality Gate)
。它的设计哲学是“够用就好”,这恰恰是它能在真实生产环境中大规模落地的关键。我们线上最大的单表校验是电商订单明细表(日增量2亿行),但GE并不需要扫描全部数据。我们通过
batch_spec
参数指定只校验当天分区+随机采样1%的行(约200万行),配合
mostly: 0.995
(允许0.5%的异常值)的宽松策略,整个校验在12分钟内完成。如果真要100%扫描PB数据,那说明你的数据管道本身就有问题——要么是ETL逻辑太重,要么是数据质量差到必须逐行排查。GE的正确用法是:在数据进入宽表/事实表前,在轻量级的Staging层做快速校验;真正的深度探查(如全量字段分布分析)交给专门的Data Profiling工具(如Deequ或自研采样服务)。这种分层治理思想,让我们在资源有限的情况下,把90%的质量风险拦截在了源头。记住:
一个能在5分钟内告诉你“数据有问题”的工具,远比一个需要2小时才能给出“完美报告”的工具更有业务价值
。
3. 实操全流程:从零开始搭建可落地的数据验证体系(含完整命令与配置)
3.1 环境初始化:避开pip install的三大陷阱
安装GE看似简单,但新手常掉进三个坑,导致后续所有操作失败。我按顺序列出安全做法:
-
虚拟环境必须隔离 :绝不要在系统Python或全局conda环境中安装。我们统一使用
python -m venv ge_env创建,然后source ge_env/bin/activate(Linux/Mac)或ge_env\Scripts\activate.bat(Windows)。这是为了防止GE的依赖(如ruamel.yaml)与现有项目冲突。曾有个项目因为ruamel.yaml==0.17.21和pandas==1.5.3的依赖冲突,导致YAML解析失败,排查了两天才发现是环境混用。 -
安装命令必须带
--no-deps:官方文档推荐pip install great-expectations,但这会强制安装所有可选依赖(包括sqlalchemy,psycopg2,pyspark等),而你很可能只需要其中一两个。正确的做法是:pip install --no-deps great-expectations pip install sqlalchemy psycopg2-binary # 只装你需要的数据库驱动这样能精准控制依赖版本,避免
psycopg2编译失败(尤其在M1芯片Mac上)。 -
初始化命令必须指定项目路径 :运行
great_expectations init时,务必先进入你的项目根目录(如/home/user/my_etl_project),再执行。GE会在当前目录下创建great_expectations/子目录。如果误在/tmp下初始化,你会得到一个孤立的配置,无法与你的ETL代码集成。初始化过程中,它会问你“Where is your data?”,这里别选“Files on my file system”,直接选“Database (SQL)”,因为我们的真实数据99%都在数据库里。
提示:初始化完成后,立刻检查
great_expectations/great_expectations.yml中的datasources部分。确保execution_engine配置为sqlalchemy,且credentials字段是占位符(如host: ${HOST}),而不是明文密码。密码必须通过环境变量注入,这是安全红线。
3.2 数据源配置:如何让GE安全、稳定地连接你的生产数据库
GE的数据源配置是整个体系的基石,配置错误会导致后续所有校验失败。以PostgreSQL为例,完整的
great_expectations.yml
片段如下:
datasources:
prod_postgres:
class_name: Datasource
execution_engine:
class_name: SqlAlchemyExecutionEngine
credentials: ${POSTGRES_CREDENTIALS}
data_connectors:
default_runtime_data_connector_name:
class_name: RuntimeDataConnector
batch_identifiers:
- runtime_batch_identifier_name
default_inferred_data_connector_name:
class_name: InferredAssetSqlDataConnector
include_schema_name: true
关键点解析:
-
credentials必须用环境变量 :在.env文件中设置POSTGRES_CREDENTIALS='{"host": "prod-db.company.com", "port": "5432", "username": "ge_reader", "password": "your_secure_password", "database": "analytics"}',然后在Python启动脚本中加载:from dotenv import load_dotenv; load_dotenv()。绝不要把密码写在YAML里!我们曾因一次误提交,导致数据库凭证泄露,被迫全量轮换密码。 -
include_schema_name: true是关键开关 :PostgreSQL默认schema是public,但很多企业会按业务域划分schema(如sales,marketing,finance)。如果设为false,GE会找不到sales.orders表,只认orders。这个参数决定了GE能否正确解析全限定表名。 -
权限最小化原则 :为GE创建专用数据库用户(如
ge_reader),只授予SELECT权限,且限制在目标schema内。我们甚至用pg_hba.conf限制该用户只能从数据平台服务器IP访问,杜绝越权风险。
配置完成后,用GE自带的验证命令测试连通性:
great_expectations datasource new
# 选择"Test a configuration" -> 输入上面配置的datasource名称
# 如果返回"SUCCESS! Your configuration is valid!",说明连接成功
注意:如果遇到
OperationalError: (psycopg2.OperationalError) FATAL: password authentication failed,90%概率是环境变量未加载或密码错误;如果是ModuleNotFoundError: No module named 'psycopg2',说明你漏装了数据库驱动。
3.3 创建第一个Expectation Suite:从“探索性分析”到“契约化声明”
Expectation Suite(期望套件)是GE的核心资产,它相当于数据质量的“接口定义文件”。创建过程分两步:先探索数据,再固化规则。
第一步:用CLI自动生成基础Suite
假设我们要校验
sales.orders
表,运行:
great_expectations suite new \
--datasource-name prod_postgres \
--batch-request '{"datasource_name": "prod_postgres", "data_connector_name": "default_inferred_data_connector_name", "data_asset_name": "sales.orders"}' \
--suite-name orders_quality_suite
这个命令会启动Jupyter Notebook,自动连接数据库,对表进行采样分析(默认1000行),并生成一份包含20+条基础规则的草稿,如:
-
expect_table_row_count_to_be_between(min_value=1000, max_value=100000) -
expect_column_values_to_not_be_null("order_id") -
expect_column_values_to_be_unique("order_id")
第二步:人工审核与精炼
自动生成的规则只是起点,必须人工介入。我们发现三个必须修改的点:
-
删除冗余规则 :
expect_column_values_to_not_be_null("updated_at")在我们的业务中是允许为空的(新订单创建时无更新时间),直接删掉。 -
收紧宽松参数 :
expect_column_values_to_match_regex("phone", regex="^1[3-9]\d{9}$", mostly=0.95)中的mostly=0.95太松,风控要求必须100%合规,改为mostly=1.0。 -
添加业务强约束 :自动生成不会懂业务逻辑。我们手动加入:
# 在suite文件中添加 expectation_configuration = ExpectationConfiguration( expectation_type="expect_column_pair_values_A_to_be_greater_than_B", kwargs={ "column_A": "order_amount", "column_B": "discount_amount", "or_equal": True, "mostly": 1.0 } ) suite.add_expectation(expectation_configuration)
这个规则确保“订单金额”永远大于等于“折扣金额”,这是财务审计的硬性要求。
所有人工添加的规则,必须附带注释说明业务依据,例如
# 来源:财务部《收入确认准则》第3.2条
。这能让后续接手的人一眼看懂规则背后的原因,而不是猜“为什么这里要加这个校验”。
3.4 构建Checkpoint:让校验从手动执行变成自动化门禁
Checkpoint是让GE从玩具变成生产工具的关键。我们以Airflow集成为例,展示完整流程。
Step 1:创建Checkpoint配置文件
在
great_expectations/checkpoints/
目录下新建
orders_daily.yml
:
name: orders_daily
config_version: 1.0
class_name: Checkpoint
run_name_template: "%Y%m%d-%H%M%S-orders-daily"
validations:
- batch_request:
datasource_name: prod_postgres
data_connector_name: default_inferred_data_connector_name
data_asset_name: sales.orders
data_connector_query:
index: -1 # 取最新分区(假设按日期分区)
expectation_suite_name: orders_quality_suite
- batch_request:
datasource_name: prod_postgres
data_connector_name: default_inferred_data_connector_name
data_asset_name: sales.customers
data_connector_query:
index: -1
expectation_suite_name: customers_quality_suite
注意
data_connector_query.index: -1
,这表示取最新的数据批次(如
sales.orders_20231001
),而不是固定表名。这对分区表至关重要。
Step 2:编写Airflow Operator
我们封装了一个自定义Operator,核心逻辑是调用GE Python API:
from airflow.models import BaseOperator
from great_expectations.data_context.types.base import CheckpointConfig
from great_expectations.checkpoint import Checkpoint
class GreatExpectationsOperator(BaseOperator):
def __init__(self, checkpoint_name, *args, **kwargs):
super().__init__(*args, **kwargs)
self.checkpoint_name = checkpoint_name
def execute(self, context):
# 加载Data Context
context = DataContext(context_root_dir="/path/to/great_expectations/")
# 执行Checkpoint
checkpoint = Checkpoint(
name=self.checkpoint_name,
data_context=context,
config=CheckpointConfig.from_commented_map({
"name": self.checkpoint_name,
"config_version": 1.0,
"class_name": "Checkpoint",
"run_name_template": "%Y%m%d-%H%M%S-" + self.checkpoint_name,
"validations": [...] # 从YAML读取
})
)
result = checkpoint.run()
# 关键:根据结果决定是否失败
if not result.success:
raise AirflowException(f"GE Checkpoint {self.checkpoint_name} failed!")
Step 3:在DAG中调用
from airflow import DAG
from datetime import datetime, timedelta
dag = DAG(
'sales_pipeline',
schedule_interval='0 2 * * *', # 每天凌晨2点
start_date=datetime(2023, 1, 1),
catchup=False
)
validate_orders = GreatExpectationsOperator(
task_id='validate_orders',
checkpoint_name='orders_daily',
dag=dag
)
# 后续ETL任务只有在校验通过后才执行
etl_task >> validate_orders
这样,当
orders_daily
校验失败时,Airflow会立即标记任务为
failed
,并发送告警邮件。
这才是真正的“质量门禁”——不是等数据污染下游后再补救,而是在污染发生前就亮红灯
。
4. 高阶实战技巧:解决真实世界中的5个棘手问题(附避坑清单)
4.1 问题1:如何校验“动态变化”的业务规则?(如促销活动期间的特殊阈值)
业务规则不是静态的。比如“双11大促期间,订单取消率容忍上限从1%提高到5%”。如果把阈值硬编码在Expectation里,每次活动都要改代码、发版本,效率极低。我们的解决方案是: 用外部配置驱动Expectation参数 。
实现步骤:
-
在数据库中创建
business_rules表,存储规则元数据:CREATE TABLE business_rules ( id SERIAL PRIMARY KEY, rule_name VARCHAR(100) NOT NULL, -- 'order_cancel_rate_threshold' value NUMERIC(5,4) NOT NULL, -- 0.05 effective_from DATE NOT NULL, -- '2023-11-01' effective_to DATE NOT NULL, -- '2023-11-11' created_at TIMESTAMP DEFAULT NOW() ); -
在GE的Checkpoint执行前,先查询当前生效的规则值:
from sqlalchemy import create_engine engine = create_engine(os.getenv("POSTGRES_URL")) threshold = pd.read_sql( "SELECT value FROM business_rules WHERE rule_name='order_cancel_rate_threshold' AND CURRENT_DATE BETWEEN effective_from AND effective_to", engine ).iloc[0]['value'] -
动态构建Expectation:
expectation_config = ExpectationConfiguration( expectation_type="expect_column_proportion_of_unique_values_to_be_between", kwargs={ "column": "cancel_reason", "min_value": 0.0, "max_value": threshold, # 这里注入动态值 "mostly": 1.0 } )
实操心得:这个方案把“业务决策”和“技术实现”解耦了。运营同学只需在数据库里改一行记录,规则就自动生效,无需开发介入。我们上线后,大促期间的规则调整平均耗时从4小时降到3分钟。
4.2 问题2:如何让DataDocs报告“说人话”,让业务方也能看懂?
DataDocs默认的HTML报告对技术人员很友好,但业务方看到
expect_column_values_to_match_regex
这种术语就懵了。我们的改造方案是:
用自定义渲染器替换默认模板
。
具体操作:
-
复制GE默认模板:
cp -r great_expectations/render/templates/ /path/to/custom_templates/ -
修改
expectation_string.py中的render函数,添加业务语义映射:# 原始:expect_column_values_to_match_regex("phone", "^1[3-9]\d{9}$") # 改造后: if expectation_type == "expect_column_values_to_match_regex": if "phone" in kwargs.get("column", ""): return "【手机号格式】必须为中国大陆11位手机号(如13812345678)" elif "email" in kwargs.get("column", ""): return "【邮箱格式】必须符合标准邮箱格式(如user@domain.com)" -
在
great_expectations.yml中指定自定义模板路径:data_docs_sites: local_site: class_name: SiteBuilder store_backend: class_name: TupleFilesystemStoreBackend base_directory: uncommitted/data_docs/local_site/ custom_templates_path: /path/to/custom_templates/
效果是:DataDocs报告中,每条规则旁边都显示“【手机号格式】...”这样的业务语言,业务方能直接对照验收。我们做过AB测试,业务方对报告的接受度从32%提升到89%。
4.3 问题3:如何避免“校验风暴”?当数百张表同时校验时的性能瓶颈
在数据平台初期,我们曾为200+张表配置了校验,结果每天凌晨2点,GE发起200+个并发数据库连接,直接把PostgreSQL的
max_connections
打满,导致线上查询超时。根本原因是:
GE默认为每个Validation创建独立连接,没有连接池复用
。
解决方案是强制GE使用连接池:
-
在
great_expectations.yml中,为datasource配置connection_string时,追加连接池参数:connection_string: postgresql+psycopg2://user:pass@host:5432/db?pool_size=10&max_overflow=20 -
更关键的是,在Python代码中显式管理连接:
from sqlalchemy import create_engine from great_expectations.execution_engine import SqlAlchemyExecutionEngine # 创建带池的引擎 engine = create_engine( os.getenv("POSTGRES_URL"), pool_size=10, max_overflow=20, pool_pre_ping=True, # 每次使用前检测连接有效性 pool_recycle=3600 # 1小时后回收连接,防长连接失效 ) # 将引擎注入GE Execution Engine execution_engine = SqlAlchemyExecutionEngine(engine=engine) -
对非核心表,启用异步校验:在Checkpoint中设置
run_validation=False,只生成DataDocs,不阻断流程。
注意事项:
pool_pre_ping=True是救命参数。我们曾因数据库主从切换,导致GE持有大量失效连接,启用了此参数后,故障率下降99%。
4.4 问题4:如何处理“脏数据惯性”?当历史数据长期不达标,无法一步到位修复时
现实很骨感:很多老系统的历史数据质量极差,如果一上来就设
mostly=1.0
,校验永远失败,团队会放弃使用GE。我们的渐进式策略是:
三阶段阈值爬坡法
。
-
阶段一(第1周):观测模式(Observation Mode)
所有Expectation的mostly设为0.0,即“只记录,不阻断”。DataDocs会清晰显示每条规则的失败率(如expect_column_values_to_not_be_null("user_id")失败率92%),让团队直观看到问题规模。 -
阶段二(第2-4周):容忍模式(Tolerance Mode)
根据观测数据,为每条规则设定合理容忍度。例如,user_id为空的问题集中在2018年前的老数据,我们设mostly=0.99,并添加注释# 允许2018年前历史数据存在空值,新数据必须100%合规。 -
阶段三(第5周起):强制模式(Enforcement Mode)
对新接入的数据流(如2023年10月后的新表),mostly=1.0强制执行;对老表,维持容忍度,但要求每月降低0.5%的容忍度,直到达标。
这个策略让团队从“抵触校验”变为“主动治理”,6个月内,核心表的
null
率从92%降至0.3%。
4.5 问题5:如何与现有监控体系(如Prometheus)打通,实现统一告警?
GE的默认告警(邮件/Slack)是孤岛。我们需要把校验失败事件推送到公司统一的Prometheus+AlertManager体系。实现方案是: 用Custom Action Hook注入Metrics上报逻辑 。
在
great_expectations.yml
中,为Checkpoint添加Action:
actions:
- name: send_to_prometheus
action:
class_name: CustomActionClass
module_name: great_expectations_custom_actions
webhook_url: http://prometheus-pushgateway:9091
然后在
great_expectations_custom_actions.py
中:
from prometheus_client import CollectorRegistry, Gauge, push_to_gateway
class CustomActionClass:
def __init__(self, data_context, **kwargs):
self.registry = CollectorRegistry()
self.gauge = Gauge('ge_validation_result', 'GE validation status',
['checkpoint', 'suite', 'expectation'], registry=self.registry)
def _run(self, validation_result, **kwargs):
for result in validation_result.results:
status = 1.0 if result.success else 0.0
self.gauge.labels(
checkpoint=kwargs.get('checkpoint_name'),
suite=result.expectation_config.kwargs.get('expectation_suite_name'),
expectation=result.expectation_config.expectation_type
).set(status)
# 推送到Pushgateway
push_to_gateway('http://prometheus-pushgateway:9091', job='ge', registry=self.registry)
这样,所有校验结果都变成Prometheus指标,可以和CPU、内存、API延迟等指标放在同一Grafana看板中,告警规则也统一管理。运维同学再也不用切多个系统查问题了。
5. 常见问题速查表:那些让你抓狂的报错,其实都有标准解法
| 报错信息 | 根本原因 | 解决方案 | 实操验证 |
|---|---|---|---|
No module named 'great_expectations'
| Python环境未激活或安装路径错误 |
运行
which python
确认当前Python路径,然后
/path/to/venv/bin/pip install great-expectations
|
在venv中执行
python -c "import great_expectations; print(great_expectations.__version__)"
|
ValidationError: 'None' is not of type 'string'
|
YAML配置中存在未定义的环境变量占位符(如
${DB_HOST}
未设置)
|
运行
printenv | grep DB
检查环境变量,或在Python中
import os; print(os.getenv('DB_HOST'))
|
在
great_expectations init
前,先执行
export DB_HOST=localhost
|
sqlalchemy.exc.OperationalError: (psycopg2.OperationalError) server closed the connection unexpectedly
| 数据库连接超时或网络不稳定 |
在
great_expectations.yml
的
connection_string
中添加
?connect_timeout=30&keepalives=1
|
使用
telnet db-host 5432
测试端口连通性
|
great_expectations.exceptions.InvalidBatchRequestError: Data asset 'sales.orders' does not exist
|
data_asset_name
拼写错误,或PostgreSQL schema未在
include_schema_name
中启用
|
运行
psql -c "\dt sales.*"
确认表存在,检查
great_expectations.yml
中
include_schema_name: true
|
在CLI中执行
great_expectations datasource explore prod_postgres
查看可识别的表列表
|
great_expectations.exceptions.CheckpointError: No validations found in checkpoint
|
Checkpoint YAML中
validations
字段缩进错误,或
expectation_suite_name
拼写与实际文件名不一致
|
用YAML在线校验器(如https://yamlchecker.com/)检查缩进;确认
great_expectations/expectations/
下存在
orders_quality_suite.json
|
运行
great_expectations checkpoint list
查看已注册的Checkpoint
|
最后分享一个小技巧:当你不确定某条Expectation是否写对时,别急着跑Checkpoint。先用GE的
validator交互模式快速验证:great_expectations validator add \ --datasource-name prod_postgres \ --asset sales.orders # 进入交互式环境后,直接输入: v.expect_column_values_to_not_be_null("order_id") v.save_expectation_suite(discard_failed_expectations=False)这种“所见即所得”的调试方式,比反复修改YAML再跑Checkpoint快10倍。我在写这篇教程时,所有Expectation都是先在这里验证通过,再固化到正式配置里的。
我在实际使用中发现,GE最大的价值不是它能发现多少问题,而是它迫使团队坐在一起,把模糊的“数据应该干净”变成精确的“
order_id
字段必须100%非空且唯一,
created_at
必须在
2023-01-01
之后”。这种共识一旦建立,数据质量问题就从“谁的锅”变成了“怎么修”,整个协作效率会质变。如果你今天只记住一件事,那就是:
不要把GE当成一个工具,而要把它当作一场数据质量的集体承诺仪式——每一次
ge checkpoint run
,都是在重申这份承诺
。

87

被折叠的 条评论
为什么被折叠?



