datadiffer

io.github.gauthierpiarrette由 GitHub 账号 gauthierpiarrette 发布v0.1.0更新于 Oct 25, 2026

Read-only table diffs with segment attribution: which slice of your data changed.

已验证STDIO仅桌面数据库数据与分析

概览

AI 生成的概览

只读的表对比服务器,让助手比较两张表,查看哪些行和列发生变化,以及变化集中在哪个数据切片。

可以做什么
列出已配置的连接,并比较两张表或两个数据源的 schema 差异(本地文件、DuckDB、Postgres、Snowflake)。先运行轻量的差异摘要作为预检,再执行完整对比。生成完整差异报告:新增、删除和修改的行数,各列的变更率,以及显示哪个数据切片过度集中的分段归因。连接通过本地配置文件中的名称引用,超出限制的请求会返回结构化拒绝。
适用场景
适合助手或编码代理需要核对自己所做的数据或管道改动时使用,例如比较开发环境与生产环境,或将拉取请求副本与主分支对比,并说明差异集中在何处,而不只是判断两张表是否一致。
运行要求
以 stdio 在本地运行,通常通过 uvx 或带 MCP 附加组件的 pip 安装。需要 datadiffer.toml 配置文件,其路径由环境变量 DATADIFFER_CONFIG 指定,可用 init 命令生成模板。Postgres、Snowflake 的仓库访问在该文件中配置;本地 Parquet、CSV 和 DuckDB 无需凭据。对比在本地 DuckDB 中执行,每侧上限为 5000 万行和 10 GiB。
安装前请注意
工具为只读,凭据不经过工具参数,而是保存在本地配置文件中,因此应保护该文件。Postgres 读取不做快照,结果可能反映正在变化的表。分段归因仅为描述性,不能说明因果关系。大型对比受上限限制,可能需要缩小范围。

安装

在 SourceWeft 中

  1. 打开 控制台中的 datadiffer,将其添加到工作区。
  2. 为需要使用其工具的对话启用该服务。

Desktop only,通过 STDIO。 STDIO 服务会启动本地进程,因此需要 SourceWeft 桌面宿主。

其他 MCP 客户端

参照 仓库 中的启动说明。

README

datadiffer

Diff two tables. See what changed, and which slice of your data it's concentrated in.

98.6% of modified rows have country = 'DE' (8.87x over-represented)

[PyPI] [CI] [License: MIT] [Python 3.10+]

datadiffer compares two tables (dev vs. prod, PR vs. main, source vs. destination) and tells you what changed and where it's concentrated: rows added / removed / modified, per-column change rates, and segment attribution.

Built for the era when agents write your pipelines and someone has to check their work. A maintained, MIT-licensed successor to the archived data-diff.

Try it in 60 seconds

No credentials, no config, no account. It generates its own data:

bash
uvx datadiffer demo

[datadiffer demo]

datadiffer-demo/orders_prod.parquet vs datadiffer-demo/orders_dev.parquetkey: order_id (inferred from *_id naming)rows: +800 added  -250 removed  ~432 modified  49318 unchanged┏━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┓┃column ┃ changed rows ┃ % of matched┃┡━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━┩│amount │          432 │        0.87%│└───────┴──────────────┴─────────────┘-> 98.6% of modified rows have country = 'DE' (8.87x over-represented)   93.2% of added rows have plan = NULL (63.19x over-represented)sample changes:  [order_id=0]  amount: 5.0 -> 7.1  [order_id=1]  amount: 6.37 -> 6.38  [order_id=117]  amount: 32.4 -> 34.5  [order_id=234]  amount: 59.8 -> 61.9  [order_id=351]  amount: 87.2 -> 89.3DIFF FOUND

That last block is the point. A diff tells you 432 rows changed; datadiffer tells you they're almost all German orders, which is the difference between "something moved" and "the VAT change landed."

Install

bash
pip install datadiffer                      # local files: Parquet, CSV, DuckDBpip install 'datadiffer[snowflake]'         # + Snowflakepip install 'datadiffer[postgres]'          # + Postgrespip install 'datadiffer[mcp]'               # + MCP server for AI agents

Use it

bash
# local filesdatadiffer diff prod.parquet dev.parquet
# DuckDBdatadiffer diff prod.duckdb:orders dev.duckdb:orders
# Postgres (attached read-only)datadiffer diff orders orders_v2 --source "postgresql://user@host:5432/db"
# Snowflake, or anything in datadiffer.toml (run `datadiffer init` first)datadiffer diff wh::analytics.orders wh::analytics_dev.orders
# cross-source: warehouse vs. a local filedatadiffer diff wh::orders orders_snapshot.parquet
# machine-readable, for scripts and CIdatadiffer diff a.parquet b.parquet --format json

Exit codes follow the GNU diff convention: 0 no differences, 1 differences found, 2 operational error.

Useful flags: --key (inferred when omitted), --where, --columns / --exclude-columns, --sample-limit, --no-attribution, -q.

In your pull requests

datadiffer-action posts the report as a sticky PR comment:

datadiffer: ANALYTICS.ORDERS vs ANALYTICS_PR_482.ORDERS: differences found ❌

+800 added · −250 removed · ~432 modified · 49,318 unchanged (2.96% of base rows affected) Policy: max-changed-rows-pct exceeded: 2.96% > 0.5%

ColumnChanged rows% of matched
amount4320.87%

Where it's concentrated: 98.6% of modified rows have country = 'DE' (8.87× over-represented) 93.2% of added rows have plan = NULL (63.19× over-represented)

yaml
- uses: gauthierpiarrette/datadiffer-action@v1  with:    config: datadiffer.toml          # holds the warehouse connection    table-a: wh::ANALYTICS.ORDERS    schema-map: "ANALYTICS=ANALYTICS_PR_${PR_NUMBER}"    max-changed-rows-pct: "0.5"  env:    SNOWFLAKE_PRIVATE_KEY: ${{ secrets.SNOWFLAKE_PRIVATE_KEY }}

Running dbt? docs/dbt-ci.md turns dbt ls --select state:modified into one diff per changed model, each with its own comment.

For AI agents (MCP)

Let a coding agent verify its own data changes:

bash
datadiffer init          # scaffold datadiffer.toml, then add the server to your client
json
{ "mcpServers": { "datadiffer": { "command": "datadiffer", "args": ["mcp"] } } }

Any MCP client works. datadiffer init prints the server entry to paste, including a uvx form for clients that prefer no global install.

Four read-only tools: list_connections, schema_diff, diff_summary (cheap preflight), diff_tables (full report). Credentials never pass through the model. Tools take connection names from your local datadiffer.toml, never DSNs. Over-cap requests come back as structured refusals with a remedy, so the agent can self-correct instead of failing.

What makes it different

Most diff tools answer whether two tables match. datadiffer answers what changed and where: which columns moved, and which slice of the data the change is concentrated in.

ToolUse it instead when
DatafoldYou need billion-row cross-database reconciliation, a collaboration UI, lineage/impact analysis, and a support contract.
SQLMesh table_diffYou already run SQLMesh and diff within a single gateway (cross-database diffing is a Tobiko Cloud feature).
RecceYou want a dbt-native PR review UI and your whole workflow is dbt.
Google DVTYou're validating a migration across 17 warehouse types and want pass/fail validation with YAML configs.
datacompyYou're comparing two pandas/Spark/Polars DataFrames inside one process.

datadiffer is for the case in between: one command, no platform, works from your terminal, your CI, or your agent, and it explains itself.

Migrating from data-diff / reladiff

Same job, different flags:

data-diff / reladiffdatadiffer
data-diff DB1 table1 DB2 table2datadiffer diff <a> <b> (locators or --source/--target)
-k, --key-columns--key (repeatable, or comma-separated)
-c, --columns--columns
-w, --where--where (validated: single boolean expression, no subqueries)
--json--format json (stable schema v1)
-l, --limit--sample-limit

Differences worth knowing: keys are inferred from declared constraints or *_id conventions when you omit --key; unknown column names in filters are an error, never silently ignored; and exit code 1 means "diff found" (2 is reserved for operational errors), so CI can tell them apart.

Not yet ported: checksum-bisection hashdiff for very large cross-database diffs, which is reladiff's headline capability, plus MySQL, Oracle, ClickHouse, Trino and the rest of its connector list. If you need those today, use reladiff; the bisection port is the top item on our v0.2 roadmap and will credit its author.

Full command mapping and behavior differences: docs/migrating-from-data-diff.md.

Scope and limits (v0.1)

  • Warehouses: Snowflake, Postgres, DuckDB, Parquet, CSV. BigQuery is next (v0.1.1).
  • Every diff runs in local DuckDB. Postgres is attached read-only and scanned in place; Snowflake is pulled once over Arrow with only the needed columns. Both are capped at 50M rows and 10 GiB per side, so narrow the comparison with --where. Pushing the comparison into the warehouse, and lifting that cap with checksum bisection, are the next two pieces of work.
  • Postgres reads are unsnapshotted (the report says so in execution.snapshot); Snowflake pulls are a single consistent SELECT.
  • Segment attribution is single-column, categorical, and descriptive. It says "over-represented", never causal.

Project

MIT, no CLA, no telemetry. The report schema is frozen at v1 and contract-tested, so pipelines and agents that parse it keep working across releases. Dependencies are deliberately few: DuckDB, PyArrow, sqlglot, click, rich.

What's next

BigQuery, then checksum-bisection hashdiff so large cross-database diffs stop needing a row cap (ported with credit to reladiff), then more connectors. Tracked in issues. Comment on the one you need and it moves up.

Contributing

bash
git clone https://github.com/gauthierpiarrette/datadiffer && cd datadifferuv sync --group devuv run pytest -q            # warehouse tests skip unless credentials are setuv run ruff check .

Prior art gratefully acknowledged: data-diff and reladiff (Erez Shinan), whose checksum-bisection design v0.2 will port; Adtributor (Microsoft Research) for the attribution scoring; and DuckDB, which makes all of this fast enough to be boring.

License

MIT

来源:README.md,提交 05948c1

工具

0
SourceWeft 尚未在沙箱中启动过该软件包,因此其工具未知。

版本历史

1
  1. v0.1.0最新Sep 16, 2026

评分

已满足适用检查项的 50%

该评分衡量此收录条目的完整程度,依据注册中心条目、端点与公开来源计算得出。它不是对服务器本身的评价,也不表示服务器安全或当前可用:可连通性是带日期的检查结果,评分也不包含安装量或用户评价。

  • 近 30 天内可连通25 分

    请保持端点能够响应 MCP 握手;SourceWeft 每 30 天探测一次。

  • 已声明认证方式10 分

    请在注册中心条目中声明凭据请求头,或保持端点能够响应探测,以便判定其认证方式。

  • 已列出工具15 分

    请让服务器在无凭据时响应 tools/list,或发布可在沙箱中无凭据启动的软件包。

  • 描述必需15 分
  • 图标10 分
  • 文档15 分
  • 许可证10 分