データカタログ3回失敗して気づいた、ようやく「使われた」理由
Collibra、Atlas、そして3度目の正直。メタデータ管理の落とし穴と、チームに定着させた運用設計パターンをデータエンジニアの実体験から
データカタログ本番運用で学んだ、ようやく「使われる」ようになった話
先日プロジェクトで3回目のデータカタログ導入に踏み切ったんです。正直、前2回は失敗でした。最初は「便利なツールがあれば解決する」と思い込んでた。でも本当は、組織とプロセスの話だったんですよね。
今回、やっと「使われるデータカタログ」になってきたので、その経験を書きます。うちのチームがぶつかった現実と、どう乗り越えたかって話です。
なぜ前2回は失敗したのか
1回目はCollibra、2回目はAtlasを導入しました。どちらも「これで全部解決する」という期待値で始まった。でも3ヶ月後には、誰も使ってない状態に。
理由は単純でした。メタデータを誰が書くんだ問題。データエンジニアは忙しいし、ビジネス側は何を書いたら良いか分からない。その結果、カタログは古い情報でいっぱいになって、信頼を失うんです。
3回目の今、うちが学んだのはこれです:
- ツール選びより運用設計が9割。何を選ぶかより、誰が何を入力するかのほうが重要だったんだ
- 完璧を目指さない。80%の情報でいいから、最初は小さく始める。100点を目指して失敗するより、60点でスタートして改善するほうがマシ
- 強制じゃなく、メリットで動かす。“これを書かないと怒られる”じゃなく、“これがあると便利”という体験を先に作る。そこが大事
今回の構成:小さく、回す、改善する
graph TB
subgraph "Data Sources"
A["BigQuery<br/>テーブル"]
B["S3<br/>データレイク"]
C["RDS<br/>トランザクション"]
end
subgraph "Metadata Layer"
D["Apache Atlas<br/>メタデータストア"]
E["dbt docs<br/>自動生成"]
F["Manual annotations<br/>チーム入力"]
end
subgraph "Discovery Interface"
G["Slack Bot<br/>クイック検索"]
H["Web UI<br/>詳細閲覧"]
I["dbt project<br/>リネージ"]
end
subgraph "User Layer"
J["Data Users<br/>分析者"]
K["Engineers<br/>開発チーム"]
L["Business<br/>営業/企画"]
end
A --> D
B --> D
C --> D
E --> D
F --> D
D --> G
D --> H
E --> I
G --> J
H --> K
I --> L
シンプルなアーキテクチャです。中心にAtlasを置いて、入力は複数の場所から受け取る。出力も複数チャネル。そうすることで、ユーザーは自分が使いやすい場所でデータを探せるし、入力者も負担を分散できる。この設計が地味に大事だったんですよね。
実装のポイント:dbt連携が8割を占める
うちの場合、dbt との連携が本当に重要でした。ここに全力を注ぎました。
dbtプロジェクトには既に大量の情報が書いてあるんです:
- テーブルの説明
- カラムの説明
- リネージ(どのテーブルから来た?)
- テスト結果(品質指標)
これを自動的にAtlasに流し込む。わざわざ二重に書かせない。ここが秘訣。
# dbt models/staging/stg_customers.yml
models:
- name: stg_customers
description: "顧客マスタの最新スナップショット。毎日AM5時に更新。"
columns:
- name: customer_id
description: "顧客の一意識別子。本番RDSから取得。"
tests:
- unique
- not_null
- name: email
description: "顧客メールアドレス。個人情報なので外部共有不可。"
- name: created_at
description: "顧客レコード作成日。UTC。"
このYAML定義をdbt Atlasパッケージ経由で自動的にAtlasに送ります。データエンジニアは「いつものdbtの書き方」をするだけ。二重作業なし。これが運用を続けるコツです。
実装コードはこんな感じになりました:
# dbt hooks: post_hook に以下を設定
import requests
import json
from datetime import datetime
def push_to_atlas(table_name, description, columns_meta):
atlas_url = "https://atlas.internal/api/v1"
entity_payload = {
"typeName": "DataSet",
"attributes": {
"name": table_name,
"qualifiedName": f"dbt.{table_name}@prod",
"description": description,
"owner": "data-engineering",
"lastModified": datetime.now().isoformat(),
"schema": json.dumps(columns_meta)
}
}
response = requests.post(
f"{atlas_url}/entities",
json={"entities": [entity_payload]},
headers={"Authorization": f"Bearer {os.getenv('ATLAS_TOKEN')}"}
)
if response.status_code != 200:
print(f"Atlas push failed: {response.text}")
return response.json()
こうすると、dbtのCI/CDパイプラインで自動的にメタデータが最新化される。手動入力がない。地味ですが、これが続く理由です。
Slack Bot が意外に威力あり
データを探すのって、ユーザーはわざわざWeb UIを開かない。実際には「このテーブルの定義なに?」とSlackで聞きたい気持ちなんですよね。
そこで簡単なSlack Botを作りました。効果は想像以上でした。
from slack_bolt import App
from slack_bolt.adapter.aws_lambda import SlackRequestHandler
import requests
app = App(token=os.getenv("SLACK_BOT_TOKEN"))
@app.message(r"(?i)what.{0,5}(table|schema).*")
def search_table(message, say):
query = message["text"]
# Atlasに検索リクエスト
atlas_response = requests.get(
"https://atlas.internal/api/v1/search/basic",
params={"query": query},
headers={"Authorization": f"Bearer {os.getenv('ATLAS_TOKEN')}"}
)
results = atlas_response.json().get("entities", [])[:3]
if not results:
say(":thinking_face: そのテーブル見つかりませんでした...")
return
blocks = []
for entity in results:
blocks.append({
"type": "section",
"text": {
"type": "mrkdwn",
"text": f"*{entity['attributes']['name']}*\n{entity['attributes'].get('description', 'N/A')}\n_Owner: {entity['attributes'].get('owner', 'N/A')}_"
},
"accessory": {
"type": "button",
"text": {"type": "plain_text", "text": "詳細を見る"},
"value": entity['guid'],
"action_id": "view_table_details"
}
})
say(blocks=blocks)
SlackRequestHandler(app).handle(event, context)
これ、思いのほか使われます。UI立ち上げより速いし、Slackのコンテキストが切れない。分析中の会話の流れのまま「あ、そのテーブルって何ですか?」って聞けるんですよ。
メタデータの品質を保つ仕組み
正直、Atlasに3000個テーブル登録しても、半分は古い情報になります。どう防ぐか。これが本当に重要。
品質ダッシュボード を毎週表示することにしました。可視化が大事なんです。
xychart-beta
title "メタデータ品質スコア (Weekly)"
x-axis [Week1, Week2, Week3, Week4, Week5]
y-axis "Quality Score (%)" 45 --> 95
line [65, 72, 78, 82, 87]
line [55, 68, 75, 81, 85]
何を計測するのかというと、こんなメトリクスです:
def calculate_metadata_quality(atlas_client):
all_entities = atlas_client.search_all(type_name="DataSet")
quality_metrics = {
"has_description": 0,
"has_owner": 0,
"has_sla": 0,
"last_updated_recent": 0, # 30日以内
"has_column_descriptions": 0
}
for entity in all_entities:
attrs = entity["attributes"]
if attrs.get("description"):
quality_metrics["has_description"] += 1
if attrs.get("owner"):
quality_metrics["has_owner"] += 1
if attrs.get("sla"):
quality_metrics["has_sla"] += 1
last_modified = datetime.fromisoformat(
attrs.get("lastModified", "2000-01-01")
)
if (datetime.now() - last_modified).days < 30:
quality_metrics["last_updated_recent"] += 1
schema = json.loads(attrs.get("schema", "{}"))
if all(col.get("description") for col in schema.get("columns", [])):
quality_metrics["has_column_descriptions"] += 1
total = len(all_entities)
return {
metric: (count / total * 100)
for metric, count in quality_metrics.items()
}
# これを毎週Slackチャネルに投稿
毎週金曜17時に#data-governanceチャネルに投稿します。すると競争心が生まれるんですよ。「うちのチームのスコア下げたくない」って。ゲーム化って大事だなと実感しました。
本番で直面した落とし穴
PII(個人識別情報)の管理が地獄でした。これは予想外でした。
カタログに「customer.email」と書く。そしたら営業さんがそのテーブルを分析ダッシュボードで晒してしまう。SOC2監査が来たとき、大問題になります。
今は、メタデータにタグを付けるようにしました。これが最小限の防御線。
models:
- name: customers
columns:
- name: email
description: "..."
meta:
pii: true # ← これが重要
classification: "confidential"
access_control: "restricted"
このメタデータを元に、自動的にアクセス制御を適用します。dbtの実行時に確認。
def check_pii_compliance(model_name, columns):
for col in columns:
if col.get("meta", {}).get("pii"):
# 本番で実行される前に警告
print(f"⚠️ {model_name}.{col['name']} contains PII")
# BigQuery RLS を自動適用
apply_rls_policy(model_name, col['name'])
チーム定着までの3ヶ月
正直、最初は「また導入か…」という雰囲気でした。だから段階的に進めました。焦らずが大事。
月1:Slack Bot だけ使わせる
- 「データ探すときはBotに聞いてみて」と紹介
- 1日5回くらい質問が来て、回答を整える
- 認知が広がる
月2:dbt 連携を見せる
- 「あ、自動的に更新されてる」ってのに気づく
- テーブル説明を書くモチベーション上がる
- 手作業じゃないって分かると態度が変わる
月3:品質ダッシュボード公開
- スコア競争が始まる
- 「うちのチーム88%だ。あっちは75%…」
- 自然と説明を充実させるようになる
今、メタデータ品質スコアは 82% です。悪くない数字だと思う。
ツール選びの現実
Atlasを選んだ理由は「Hadoopエコシステムとの相性」と「無料」。Collibra は本当に高い(年1000万超)。Alation は機能いっぱいすぎて、チームが迷う。
小さく始めるならこうです:
| ツール | 費用 | 学習曲線 | 自動化 | おすすめ度 |
|---|---|---|---|---|
| Atlas | 無料(OSSバージョン) | 中 | 高 | ⭐⭐⭐⭐⭐ |
| Collibra | 年1500万+ | 低 | 中 | ⭐⭐⭐ (大企業向け) |
| Alation | 年800万+ | 低 | 中 | ⭐⭐⭐⭐ (機能重視) |
| DataHub | 無料 | 高 | 高 | ⭐⭐⭐⭐ (Atlasの次点) |
| Amundsen | 無料 | 中 | 中 | ⭐⭐⭐ (Uber版の思想好きなら) |
正直に言うと、自動化できない手作業が増えるなら、無料ツールはお金の無駄です。dbt との連携を前提に選ぶ。データの全体像を見る仕組みが最初から必要。ここをケチるとツール導入は失敗します。
今後の課題
データリネージが50%くらいの精度なんです。Collectorをもっと増やしたい。それと、ビジネス側のメタデータ定義 をどう組み込むか。テーブルの説明だけじゃなく、「このテーブルはいつ使うの?」「どの部門が責任者?」って情報がないんですよね。
データ品質管理とセットで、メタデータ品質とデータ品質の両面で見ていく予定です。
正直、AIで自動抽出とか言う人もいますが、うちのケースでは 人間の説明が必須。チームの知識がメタデータに集積される。それが本当の価値なんです。
まとめ
データカタログの本当の価値は、ツールじゃなく「組織の知識を可視化する」こと。導入は以下の順序で進めるといいですよ:
- 小さく始める — 全テーブル登録より、よく使うテーブルを100%で。完璧を目指さない
- 自動化を優先 — dbtとの連携で手作業を減らす。ここが本当に大事
- 出力を複数化 — Web UI だけより、Slack Bot で気軽にアクセスできるようにする
- 品質を可視化 — スコア競争で自然と定着する。人間のモチベーションを上手く使う
- アクセス制御と結合 — PII 管理や SLA を組み込む。ガバナンスと一体化させる
3回失敗してようやく分かったことです。今、うちのチームはデータの場所と説明に困らなくなった。これが「使われるカタログ」の状態なんだと思う。次は、このメタデータをAIで活用する段階に進みたいと考えています。
皆さんはどうしてます?ツール導入の落とし穴で困ったことあれば、ぜひ共有してもらいたい。