Article

データ統合に潜む落とし穴:社内システムのサイロ化を防ぐには

高田晃太郎
データ統合に潜む落とし穴:社内システムのサイロ化を防ぐには

複数の業界調査では、データ活用の初期フェーズで全作業時間の60〜80%が統合・前処理に費やされると報告されています¹。一方で、この数値は役割や範囲の定義次第で誇張されがちだという指摘もあり、再現性のあるメトリクス設計が欠かせません²。さらに、ガバナンス(ルールと責任の枠組み)と統合基盤が弱い組織では、データ取得から意思決定までのリードタイムが平均で数日から数週間に延び、変化対応の遅れが機会損失に直結します³,⁷。現場ではしばしば、データ統合の手戻りがアプリケーション開発の数倍のコストに膨らみ、復旧の達成目標であるSLO(Service Level Objective)が未達になりやすいという課題が観測されます。技術的難易度そのものよりも、データ契約(公開仕様と互換性ルール)・スキーマ進化(後方互換を保つ拡張)・オーナーシップ(責任所在)の欠如が本質的なボトルネックです。サイロ化は偶然ではなく、日々の小さな意思決定の積み重ねで必然的に起きます⁷。ここでは原因と対策を構造化し、現場で即使える実装断片と運用の要点を示します。

社内サイロ化の構造的原因と見えないコスト

サイロ化は、組織の境界とシステムの境界が一致しない時に顕在化します。ドメインごとに最適化されたアプリケーションが増えるほど、データの解釈や粒度、主キー設計が微妙にずれ、同一概念が異なるID・カーディナリティで重複表現されます。初期はETL(Extract, Transform, Load: 抽出・変換・格納)のパッチでつなげますが、ビジネスイベントの意味づけが各パイプラインで再解釈されるため、時間の経過とともに矛盾が累積します。結果として、同じKPI(重要業績評価指標)に複数値が併存し、経営判断の遅延や意思決定の分断が起こります³。

見えないコストは三層で発生します。まずエンジニアリング面ではパイプラインのスパゲッティ化により変更影響範囲の推定が困難となり、デプロイの心理的安全性が損なわれます。次にオペレーション面では、リカバリ手順が個人依存になり、MTTR(Mean Time To Recovery: 平均復旧時間)が長期化します。最後にビジネス面では、データ鮮度や完全性のSLOが欠落しているため、分析結果の信頼度が下がり、現場は手作業の補正を常態化させます。これらが恒常化すると、データ基盤刷新の投資対効果は短期に示しづらくなり、先送りの動機が強まります⁷。

逆にいえば、分断は設計原則と契約で予防できます。データは暗黙ではなく契約(Contract)で公開し、変更はスキーマ進化ルールで明文化し、運用の期待値はSLOで可視化します。さらにドメイン境界でオーナーシップを明確にし、データを製品(Data Product)として扱う視点を持つことで、再現性のある統合が可能になります⁴,⁵。

破綻するデータ統合の典型パターン

最も多いのはポイントツーポイント連携の肥大化です。最初は数本のインテグレーションで済んでいても、機能追加のたびに新たな抽出・変換が増え、いつの間にか非同期の隠れた循環依存を含むメッシュが形成されます。可観測性(メトリクス・ログ・トレースで挙動を把握する性質)がない場合、遅延の根因が特定できず、リトライやバッファ拡張で対処するたびにコストが膨らみます⁶。次に危険なのは、共通ID戦略の欠落です。顧客・取引・在庫などのコアエンティティについて、自然キーと代理キー、バージョニング、論理削除の表現を合わせないと、結合のたびに例外処理が増えます⁴。最後に、スキーマ変更の後追い対応です。後方互換を破る変更が本番で先行し、下流がバッチでまとめて壊れる、という事態は珍しくありません⁴。

よくあるケースとして、CRM・EC・倉庫管理がそれぞれ独自の顧客IDを使い、統合レイヤでメールや電話番号のマッチングに頼る状況があります。短期的にはヒット率を上げられますが、重複と誤マージが増え、返品や与信の判定が不安定化します。統合後にMDM(Master Data Management: マスターデータ管理)を導入しても、上流システムの発行主義が揺れている限り収束しません。対策として、イベント駆動でのマスター発行と、IDの不変性・再発行ポリシーをデータ契約に格納し、下流に破壊的変更を禁止するガードレールを設けることで、改善に向かう傾向があります⁴。

アンチパターンを実装で可視化する

抽象論だけでは行動に移せません。ここでは契約と実装の断片を提示し、どこから壊れやすいのかを具体的に確認します。以降のスニペットはいずれも本番運用での検討ポイントを含みます。

サイロ化を防ぐ設計原則:契約、イベント、進化可能なスキーマ

第一に、データ契約の明文化です。APIやイベントは仕様書ではなく契約として扱い、破壊的変更の条件、フィールドの意味、遅延到着や重複の扱いを機械可読で残します。以下はOpenAPIでの契約例です。命名規則、ページネーション、冪等性キー(同一リクエストの重複実行を防ぐ鍵)を含めています⁴。

openapi: 3.0.3
info:
  title: Customer API
  version: 1.2.0
paths:
  /customers:
    get:
      parameters:
        - name: page
          in: query
          schema: { type: integer, minimum: 1 }
        - name: page_size
          in: query
          schema: { type: integer, maximum: 200, default: 50 }
      responses:
        '200': { description: OK }
    post:
      headers:
        Idempotency-Key:
          schema: { type: string }
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Customer'
components:
  schemas:
    Customer:
      type: object
      required: [customer_id, email]
      properties:
        customer_id: { type: string, description: 'Immutably assigned' }
        email: { type: string, format: email }
        status: { type: string, enum: [active, suspended] }

第二に、イベント駆動とスキーマ進化です。イベントは過去の事実を表すログであり、後から書き換えないことが前提です。スキーマは後方互換を基本とし、必要に応じてフィールド追加で進化させます⁴。以下はJSON Schemaでのイベント契約例です。

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://schemas.example.com/order/OrderCreated/1-1-0",
  "title": "OrderCreated",
  "type": "object",
  "properties": {
    "event_id": {"type": "string"},
    "event_time": {"type": "string", "format": "date-time"},
    "order_id": {"type": "string"},
    "customer_id": {"type": "string"},
    "total_amount": {"type": "number"},
    "currency": {"type": "string", "pattern": "^[A-Z]{3}$"}
  },
  "required": ["event_id", "event_time", "order_id", "customer_id"],
  "additionalProperties": false,
  "x-compat": {"backward": true, "forward": false}
}

第三に、CDC(Change Data Capture: 変更データ捕捉)での系譜保持です。アプリのDBから直接バッチ抽出するのではなく、ログベースCDCで変化をストリーム化します。以下はDebeziumコネクタの設定例です。

{
  "name": "inventory-connector",
  "config": {
    "connector.class": "io.debezium.connector.mysql.MySqlConnector",
    "database.hostname": "mysql",
    "database.port": "3306",
    "database.user": "debezium",
    "database.password": "*****",
    "database.server.id": "184054",
    "database.server.name": "store",
    "table.include.list": "store.orders,store.order_items",
    "snapshot.mode": "initial",
    "tombstones.on.delete": "false",
    "include.schema.changes": "true"
  }
}

最後に、次元・ファクトの時間表現を明確にします。効果的なのはSCD Type 2(履歴を期間で保持する手法)です。次のdbtモデルは、代理キーと有効期間を持つ顧客ディメンションを構築します。

with staged as (
  select *,
         row_number() over(
           partition by customer_id order by updated_at
         ) as rn
  from {{ ref('stg_customers') }}
),
scd as (
  select customer_id,
         md5(customer_id || coalesce(email, '') || coalesce(status, '')) as customer_sk,
         email,
         status,
         updated_at as valid_from,
         lead(updated_at) over(partition by customer_id order by updated_at) as valid_to
  from staged
)
select customer_sk,
       customer_id,
       email,
       status,
       valid_from,
       coalesce(valid_to, '9999-12-31') as valid_to,
       valid_to is null as is_current
from scd;

命名規則と時間の扱いで品質を底上げする

列名は意味と単位を含め、時間は必ずタイムゾーンを明記します。created_atはイベント発生時刻、ingested_atは取り込み時刻、processed_atは処理時刻のように用途別に分けておくと遅延解析が容易です。金額は通貨コードとセットで扱い、集計時の再計算ルールを契約に記述します。こうした細部の一貫性が、後段の解釈コストを継続的に削減します。

実装指針と運用SLO:観測可能な統合パイプラインを作る

データ統合は、構築よりも運用が勝負です。SLOは鮮度(イベント発生から可視化までの遅延)、完全性(期待レコードの到着率)、可用性(システム稼働率)の三点から設定します。例えば、重要ダッシュボードの鮮度をイベント発生後15分以内、完全性はT+1で99.5%のレコード到着、可用性は月間99.9%といった具合に「目標値の例」を定めます。違反時は自動アラートし、ユーザーに期待値のズレを可視化します。パイプラインは宣言的に管理し、依存関係とデータセット単位でのトリガを持たせます⁸。以下はAirflowの例です。

from datetime import datetime, timedelta
from airflow import DAG
from airflow.operators.python import PythonOperator

def load_orders():
    # idempotent load with upserts
    pass

def build_mart():
    # run dbt build for marts
    pass

def validate():
    # run data quality checks
    pass

def notify():
    # notify SLO breach to stakeholders
    pass

default_args = {
    "retries": 3,
    "retry_delay": timedelta(minutes=5),
}

dag = DAG(
    dag_id="orders_pipeline",
    start_date=datetime(2024, 1, 1),
    schedule_interval="*/10 * * * *",
    default_args=default_args,
    sla_miss_callback=lambda *args, **kwargs: notify(),
    catchup=False,
)

load = PythonOperator(task_id="load_orders", python_callable=load_orders, dag=dag)
mart = PythonOperator(task_id="build_mart", python_callable=build_mart, dag=dag)
check = PythonOperator(task_id="validate", python_callable=validate, dag=dag)

load >> mart >> check

品質担保には自動検査を組み込みます。Great ExpectationsやSodaのようなツールを使い、行数、ユニーク性、外部参照整合などをCI(Continuous Integration: 継続的インテグレーション)で検証します。以下はSodaCLの例です。

checks for orders:
  - row_count > 0
  - missing_count(order_id) = 0
  - duplicate_count(order_id) = 0
  - schema:
      warn:
        when schema changes: any

データ系のインシデント対応を早めるには、**データリネージュ(入力から出力までの系譜)**の記録が不可欠です。OpenLineageのイベントをジョブ実行時に送信し、どの入力がどの出力に影響したかを追跡します。次は簡易的なOpenLineageイベントです。

{
  "eventType": "COMPLETE",
  "eventTime": "2025-08-30T12:34:56Z",
  "run": { "runId": "c1a2-b3" },
  "job": { "namespace": "analytics", "name": "orders_pipeline.build_mart" },
  "inputs": [{ "namespace": "warehouse", "name": "stg_orders" }],
  "outputs": [{ "namespace": "warehouse", "name": "mart_sales_daily" }]
}

データプロダクトの境界を越える参照は、契約をまたいで行います。次のデータ契約は、公開列・品質SLO・ブレーク変更ポリシーを含みます⁵。

name: mart_sales_daily
owner: sales-analytics@s.example.com
slo:
  freshness: { target: "PT15M", objective: 0.99 }
  completeness: { target: 0.995, window: "P1D" }
contract:
  fields:
    - name: date
      type: date
      semantics: business_day
    - name: customer_id
      type: string
      semantics: immutable_id
    - name: amount_jpy
      type: number
      semantics: currency_JPY
breaking_changes:
  policy: "prohibit without new version"
  procedure: "publish v2 in parallel for 90 days"

セキュリティとプライバシーは契約の中に埋め込む

PII(個人識別情報)は列レベルで分類し、マスキングとアクセス制御を強制します。RBAC/ABAC(Role/Attribute-Based Access Control: 役割/属性ベースのアクセス制御)を活用し、役割と目的に応じてポリシー評価を自動化します。イベントやテーブルの契約にデータ分類タグを含め、監査証跡を残します。これにより、プロダクトチームは自律性を保ちつつ、全社基準に適合した形で公開できます。

組織運用:チームトポロジーと責務分界

技術だけでは持続しません。データプラットフォームチームはゴールデンパスを提供し、ドメインチームがセルフサービスでデータプロダクトを公開できる体制を整えます。標準テンプレート、観測性、サンドボックスを揃え、プラットフォームは最小の共通制約に留めます。データメッシュを採用するか集中基盤を選ぶかは、ドメインの独立性と組織の成熟度で判断します⁵。いずれにせよ、契約・SLO・課金モデルをセットにしないと、運用負債が雪だるま式に増えます。

移行は一気には進みません。まず耐障害と検知の観点から、クリティカルなKPIに紐づく数本のフローで契約化・観測化を進めます。次にID戦略と時間表現を共通化し、変更審査を軽量なアーキテクチャレビューで回せるようにします。最後にコスト可視化を行い、ストレージ・転送・コンピュートの三要素でユニットエコノミクスを公表します。可視化は政治ではなく、投資配分の判断材料として機能します。

よくある質問に先回りする実務上の勘所

バッチかストリーミングかという問いには、鮮度SLOが境界を決めます。15分以内が必須ならマイクロバッチまたはストリーム、日次で十分なら堅牢なバッチが適しています。スキーマ管理では、単一巨大レポジトリよりもドメイン別にバージョン付けし、互換性ルールを必ずテストに落としておきます。レガシーとの同居期間は長くなりがちなので、二重書き込みや二重パスを一時的に許容し、測定可能な退役計画を伴走させます。

まとめ:小さな契約から始め、観測で育てる

サイロ化は技術の失敗ではありません。契約とオーナーシップが曖昧なまま成長した結果です⁴。今日からできる一歩として、最重要のデータフローを一つ選び、契約化・SLO定義・観測の三点セットを当ててください。スキーマの互換性ルールを文章ではなく機械可読に落とし、変更レビューで自動検証を通します。数週間の運用だけでも、遅延や欠損の傾向が見え、どこに投資すれば効果が最大化するかが明確になります。組織が抱えるデータの摩擦は、設計原則と小さな成功の反復で確実に減らせます。次にどのフローで同じ型を適用しますか。意思決定の速さと品質が、そこで着実に改善していくはずです。

参考文献

  1. Flywheel. DX・データ活用の取り組み速度を上げるには? – データ整備の視点から(2020年). https://www.flywheel.jp/topics/20201013/
  2. Dodds L. Do data scientists spend 80% of their time cleaning data? Turns out, no. https://blog.ldodds.com/2020/01/31/do-data-scientists-spend-80-of-their-time-cleaning-data-turns-out-no/
  3. Talend. What are data silos? https://www.talend.com/jp/resources/what-are-data-silos
  4. Microsoft Learn. Data contracts in a data mesh. https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/scenarios/cloud-scale-analytics/architectures/data-contracts
  5. Microsoft Learn. Data domains and data mesh. https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/scenarios/cloud-scale-analytics/architectures/data-domains
  6. Argon Digital. iPaaS vs Spaghetti: The end of point-to-point integrations. https://argondigital.com/blog/general/ipaas-vs-spaghetti/
  7. OBC 360. 経済産業省のDXレポートにみる「データの横断活用」課題の指摘. https://www.obc.co.jp/360/list/post395
  8. ブレインパッド DOORS. データパイプラインとは何か? https://www.brainpad.co.jp/doors/contents/about_data_pipeline/