Dataparity について
Dataparityは、同一または異なるデータベースのテーブルを比較するCLI、MCPサーバー、ライブラリです。変更内容や偏り、リスク判定をエージェントに返し、データベース間の比較では行データを各エンジン内に保ちます。
主な機能
- 01データベース間のテーブル比較
- 02移植可能な正規行ハッシュ
- 03列単位の変更詳細
- 04変更の帰属分析とリスク判定
- 05読み取り専用のMCPツール
活用シーン
- 01本番テーブルとステージングテーブルの差分確認
- 02データベーステーブルとParquetまたはCSVの比較
- 03CIでのデータ差分チェック
MCP 対応
データソースの一覧、テーブル情報の確認、テーブル比較を行う4つの読み取り専用ツールを提供します。接続文字列ではなくデータソース名を受け取り、データベースへの書き込みは行いません。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
4掲載時のツール一覧 · 2 週間前に更新
このツールにパラメーターはありません。
詳細
Dataparity
AI エージェント向けのデータベース横断データ差分・調整ツール。ポータブルな行ハッシュを使用します。
2つのテーブルを比較し、同じデータベース内でも、異なるデータベース間でも、変更内容、変更された列、変更が集中しているデータの範囲を確認できます。 CLI、MCP サーバー、ライブラリとして動作します。MIT ライセンスです。
できること · ハッシュのポータビリティについて · インストール · CLI · MCP · ライブラリ · 仕組み · ステータス
できること
2つのテーブルとキーを指定すると、変更内容を確認できます。
HIGH 3 difference(s) found across 5 row(s) (60.00% of the left side).
left pg :: public.orders_prod (5 rows)
right mysql :: analytics.orders_staging (5 rows)
strategy checksum keys id
added 1 removed 1 modified 1 unchanged 3
where the changes are concentrated:
country = DE 4 change(s) 80.0% of changes 6.7x over-represented
sample changes:
removed key=2
modified key=3 amount
added key=6
signals:
- 1 row(s) exist only on the left
- 1 row(s) exist only on the right
- 1 row(s) differ in at least one column
自分で書く SELECT EXCEPT とは、次の3つの点で異なります。
-
異なる2つのデータベース間で動作します。 Postgres ↔ MySQL、Postgres ↔ DuckDB、 Parquet ↔ Postgres に対応します。両方の側でそれぞれのエンジン内で同じ正規行ハッシュを計算するため、 ネットワークを介してやり取りされるのはハッシュだけで、行データは送信されません。
-
変更があることだけでなく、変更の場所も示します。 「432行に差異があります」と報告する差分は、 ほとんど役に立ちません。一方、「変更された行の98.6%はドイツの注文です」と分かれば、 VAT ルールが適用されたこと、そしてほかには何も適用されていないことが分かります。
-
エージェント向けに構築されています。 読み取り専用の4つのツール、安定したJSON結果の コントラクト、コーディングエージェントが実行に移せるリスク判定 (
none/low/medium/high/critical)を備えたMCP サーバーです。
ハッシュのポータビリティについて
エンジン間で行を比較するには、値の意味を統一する必要があります。Postgres の 0.1 と
MySQL の 0.1 は、どちらも0.1に最も近い浮動小数点数であり、0.1 + 0.2 は 0.3 ではありません。
ブール値はPostgresでは true、MySQLでは 1 です。あるエンジンのタイムスタンプ精度はマイクロ秒で、
別のエンジンでは秒単位です。NULLは空文字列ではありません。
Dataparityは、すべてのエンジンに同じように適用される2つのルールでこの問題を解決します。
- すべての値にタグが付きます。 NULLは
Nとして出力され、それ以外の値は正規化されたテキストの前にVが付きます。NULLと''が混同されることはなく、実際の値がNULLと誤認されることもありません。 - すべての値には長さの接頭辞が付きます。行ハッシュにまとめる前に付与されるため、フィールド区切り文字を 含むテキスト値によって列の境界がずれて、一致を偽装されることはありません。
浮動小数点数は、固定の小数桁数に合わせて厳密な十進演算でスケーリングしてから出力するため、
0.1 + 0.2 と 0.3 は一致します。タイムスタンプはUTCに正規化され、秒単位に切り捨てられます。
ブール値はどこでも true / false として出力されます。
その結果、エンジン間でバイト単位に一致するMD5行ハッシュが得られます。これはREADME上の主張ではありません。
test/integration/canonical.test.ts で、Postgres、MySQL、DuckDBに同じ扱いにくい値を書き込み、
ハッシュが一致することを必須として検証しています。
docker run -d --name pgdiff -e POSTGRES_PASSWORD=test -e POSTGRES_DB=difftest -p 55432:5432 postgres:16-alpine
docker run -d --name mydiff -e MYSQL_ROOT_PASSWORD=test -e MYSQL_DATABASE=difftest -p 53306:3306 mysql:8
npm run test:integration
これらのテストにはデータベースが必要です。データベースに接続できない場合、テストは成功ではなく スキップとして報告されるため、テストが何も実行されていないのに実行成功となることはありません。 さらに、CIでは何かがスキップされるとジョブが失敗します。
インストール
npm install -g dataparity
インストールせずに実行することもできます。
npx dataparity --help
Node.js 22.16以降が必要です。
CLI
ソースは ~/.dataparity/config.json で一度設定します(または、DATAPARITY_CONFIG を別のパスに設定します)。
{
"sources": [
{ "name": "prod", "type": "postgres", "connectionString": "postgres://..." },
{ "name": "staging", "type": "postgres", "connectionString": "postgres://..." },
{ "name": "mysql", "type": "mysql", "host": "127.0.0.1", "port": 3306,
"user": "readonly", "password": "...", "database": "analytics" },
{ "name": "local", "type": "sqlite", "path": "data/app.db" },
{ "name": "files", "type": "duckdb", "files": ["data/orders.parquet"] }
]
}
次に、差分を確認します。
# Two tables in the same database
dataparity diff \
--left prod --right staging \
--left-table public.orders_prod --right-table public.orders_staging \
--key id
# Two tables in two different databases
dataparity diff \
--left prod --right mysql \
--left-table public.orders_prod --right-table orders_staging \
--key id --json
# Explore first
dataparity tables --source prod
dataparity describe --source prod --table public.orders_prod
終了コードは GNU diff の規約に従います。0 は一致、1 は差分あり、2 はエラーです。
そのため、CI チェックにそのまま組み込めます。
| オプション | 意味 |
|---|---|
--left、--right | 設定ファイルに記載されたソース名 |
--left-table、--right-table | 比較するテーブル |
--key | 行の照合に使用する、カンマ区切りのキー列 |
--columns | 比較する列(デフォルトでは、両方に存在するすべての列) |
--where | 両方に適用する WHERE 式 |
--max-changes | 報告する行の変更数の上限(デフォルトは 100) |
--max-attributions | 報告するアトリビューションセグメント数の上限(デフォルトは 5) |
--sample | サンプルのみを比較します。結果にはサンプルであることが示されます |
--sample-limit | 片側あたりのサンプリング行数の上限(デフォルトは 100000) |
--bucket-count | データベース間の差分比較に使用するバケット数を明示的に指定します |
--json | 機械可読形式の出力 |
認証情報はファイルに書き込まずに済むよう、ファイルの代わりに環境変数から取得できます。
export DATAPARITY_PROD_CONNECTION_STRING='postgres://...'
export DATAPARITY_MYSQL_PASSWORD='...'
MCP
claude mcp add --scope user dataparity -- npx -y dataparity mcp
または、.cursor/mcp.json に設定します。
{
"mcpServers": {
"dataparity": { "command": "npx", "args": ["-y", "dataparity", "mcp"] }
}
}
読み取り専用ツールは 4 つあります。
| ツール | 機能 |
|---|---|
dataparity_list_sources | 設定済みソースとそのエンジンタイプを一覧表示します |
dataparity_list_tables | ソース内のテーブルとその列を一覧表示します |
dataparity_describe_table | 1 つのテーブルの列、型、NULL 許容性を表示します |
dataparity_diff | 2 つのテーブルを比較し、変更内容を報告します |
ツールに渡すのはソースの名前であり、接続文字列ではありません。認証情報がモデルを経由することはありません。すべてのツールは読み取り専用であり、dataparity がデータベースに書き込むことはありません。
ライブラリ
import { diffTables, PostgresSource, MysqlSource } from 'dataparity';
const prod = await PostgresSource.connect({ connectionString: process.env.PROD_URL! });
const staging = await MysqlSource.connect({
host: '127.0.0.1', port: 3306, user: 'ro', password: '...', database: 'analytics',
});
const report = await diffTables(prod, 'public.orders', staging, 'orders_staging', {
keyColumns: ['id'],
});
if (report.risk.level === 'critical') {
console.error(report.risk.signals.join('\n'));
process.exit(1);
}
仕組み
同じデータベース → データベース内の単一の結合。 追加、削除、変更という 3 種類の分類は、アンチ結合 1 回と外部結合 1 回で構成され、すべてデータベース内で完結します。行データがデータベースの外に出ることはなく、結果は正確です。
異なるデータベース → 正規化ハッシュをバケット単位で比較。 各側で、それぞれのエンジン内においてバケットごとの件数と、互いに独立した 2 つのチェックサムを計算します。集計結果が一致しないバケットだけを行レベルまで展開するため、数行だけ異なる 10 億行のテーブルでも、転送されるのは 10 億行ではなく、少数のハッシュです。
アトリビューション。 各候補列について、変更された行におけるその列の値の分布を、テーブル全体での分布と比較します。変更された行で想定より大幅に多く見られる値は、影響を受けた範囲を示します。スコアが表すのは記述的な関連性(「過剰に多い」)であり、因果関係ではありません。
リスク。 判定では、変更の規模とスキーマの差異を考慮します。列の削除または型変更に行の追加または削除が伴う場合は critical です。スキーマに変更がなく、変更された行の割合が小さい場合は low です。
サポート対象のエンジン
| エンジン | 同一 DB | DB 間 | 備考 |
|---|---|---|---|
| PostgreSQL | はい | はい | |
| MySQL | はい | はい | |
| SQLite | はい | はい | デフォルトで読み取り専用の node:sqlite を使用 |
| DuckDB | はい | はい | Parquet、CSV、JSON を直接読み込みます |
| Parquet / CSV / JSON | — | はい | DuckDB 経由 |
boolean と 0/1 の整数は同じ論理型として扱われるため、Postgres の boolean 列は、SQLite で選択肢がなく使用される整数列と正しく比較できます。
ステータス
初期段階です。中核部分は堅牢で、実際の Postgres、MySQL、DuckDB を使ったテストも済んでいますが、機能範囲は狭く、細部には注意が必要です。
現在できること
- 同一データベース間の差分を、列単位の正確な詳細とともに確認
- Postgres、MySQL、SQLite、DuckDB 間のデータベース横断差分を確認
- スキーマ比較、変更の帰属特定、リスク判定
- CLI、MCP サーバー、型付きライブラリ API
- 設計上、読み取り専用です。認証情報がモデルに渡ることはありません
- データベース横断差分では、各エンジン内で計算した列ごとのハッシュを比較することで、変更された列を特定します。そのため、値がネットワーク経由で送信されることなく、ハッシュ比較後も列の詳細を確認できます
既知の制限
- データベース横断差分では、変更された列は特定できますが、変更前後の値は確認できません。ハッシュのみがネットワーク経由で送信されるため、値そのものがどちらのエンジンからも外に出ることはありません。同一データベース間の差分では、値も確認できます。
- JSON 列はテキストとして比較されるため、キーの順序が違うと変更として認識されます。代わりに構造を比較してください。
- 浮動小数点数と小数は小数点以下 6 桁まで比較されます。それより細かい桁では、エンジン間で最下位ビットに違いが生じる場合があります。
where句は生の SQL フラグメントです。モデルではなくエンジンに渡されますが、信頼できる入力として扱ってください。- モニター、リネージグラフ、dbt 連携、UI はありません。
コントリビューション
docs/design.md が、スコープとその背景にある重要な判断を記した正本です。動作を変更する前に読んでください。結論だけでなく、判断の理由も記録されています。
ワークフローは次のとおりです。
npm ci
npm test # unit tests
npm run test:integration # needs live Postgres + MySQL; skips if absent
npm run test:audit # every engine x every option x every error path
npm run lint
npm run typecheck
npm run build
統合テストスイートには、:55432 の Postgres 16 と、:53306 の MySQL 8 が必要です。
docker run -d --name pgdiff -e POSTGRES_PASSWORD=test -e POSTGRES_DB=difftest -p 55432:5432 postgres:16-alpine
docker run -d --name mydiff -e MYSQL_ROOT_PASSWORD=test -e MYSQL_DATABASE=difftest -p 53306:3306 mysql:8
ライセンス
MIT です。LICENSE を参照してください。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。