0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

縦持ち vs 横持ち:計測データ設計で迷わない実務ガイド

Last updated at Posted at 2025-12-21

はじめに

計測データを扱っていると、必ず一度は悩みます。

「データって、縦持ちと横持ちどっちがいいんだろう?」

  • UNION で View を作るべきか
  • 粒度違いのデータをどう扱うか
  • 指標が増えたらどうなるか

こうした悩みの多くは、
縦持ち / 横持ちを「どちらかに決めよう」とすることから生まれます。

本記事では、

  • 縦持ち・横持ちの違い
  • それぞれのメリット・デメリット
  • 計測データでの現実的な使い分け

を整理します。


結論

保存は縦持ち、利用は横持ち

これが、計測データ設計で最も事故が少ない考え方です。


縦持ちとは何か

典型的な構造(ロング形式)

fact_measurement
-----------------------------
timestamp
metric_type   -- temperature / humidity / pressure ...
value
interval_minutes
aggregation_type
source

1行が表すのは、

「いつ・何を・いくつ」

という 計測の事実 です。


縦持ちのメリット

① 計測データの本質に合っている

  • 指標が増えてもスキーマ変更不要
  • NULL 列が増えない
INSERT INTO fact_measurement
(timestamp, metric_type, value)
VALUES ('10:00', 'co2', 800);

② 粒度・集計違いを安全に扱える

  • 5分 / 1時間
  • raw / avg / max

といった 意味の違いを列で表現 できるため、

  • 生データと集計データが混ざる事故
  • UNION 時の意味破綻

を防ぎやすい。


③ 将来拡張に強い

  • 新指標
  • 新粒度
  • 新データソース

すべて 行追加 で対応できる。


縦持ちのデメリット

❌ クエリが読みにくい

SELECT
  MAX(CASE WHEN metric_type = 'temperature' THEN value END) AS temperature,
  MAX(CASE WHEN metric_type = 'humidity' THEN value END) AS humidity
FROM fact_measurement
GROUP BY timestamp;
  • CASE が増える
  • 初見で意図が読みづらい

❌ 表示・帳票向きではない

  • CSV
  • グラフ
  • BI ツール

は横持ち前提が多い。


横持ちとは何か

典型的な構造(ワイド形式)

measurement_hourly
-----------------------------
timestamp
temperature
humidity
pressure

1行が表すのは、

「ある時点の状態」

です。


横持ちのメリット

① クエリが直感的

SELECT timestamp, temperature, humidity
FROM measurement_hourly;
  • 読みやすい
  • アプリコードが素直

② 表示・集計に強い

  • ダッシュボード
  • レポート
  • 画面表示

横持ちのデメリット

❌ 拡張に弱い

  • 指標追加 = ALTER TABLE
  • NULL 列だらけ

❌ 意味の違いを混ぜやすい

temperatureが

  • 実測
  • 平均
  • 最大

のどれか分からなくなる。


計測データでの現実的な使い分け

目的 向いている形式
事実の保存 縦持ち
生データ管理 縦持ち
粒度違い統合 縦持ち
参照・集計 横持ち(View)
表示・帳票 横持ち

おすすめ構成(実践例)

① 事実テーブル(縦持ち)

fact_measurement
-----------------------------
timestamp
metric_type
value
interval_minutes
aggregation_type

② 利用者向け View(横持ち)

CREATE VIEW v_measurement_hourly AS
SELECT
  timestamp,
  MAX(CASE WHEN metric_type = 'temperature' THEN value END) AS temperature,
  MAX(CASE WHEN metric_type = 'humidity' THEN value END) AS humidity
FROM fact_measurement
WHERE interval_minutes = 60
  AND aggregation_type = 'avg'
GROUP BY timestamp;

UNION / VIEW との関係

  • 縦持ち:UNION しやすい(意味を保てる)
  • 横持ち:UNION は View 側で限定的に使う

👉 UNION は「横持ちを作るための手段」のように考えると整理しやすい。


アンチパターン:縦持ち・横持ちでよくある失敗例

アンチパターン①:最初から横持ちで保存してしまう

measurement
-----------------------------
timestamp
temperature
humidity
pressure

何が起きるか

  • 指標追加のたびに ALTER TABLE
  • NULL 列が増殖
  • 生データ/集計データが同居し始める

👉 「今は楽、将来が地獄」 な典型例


アンチパターン②:縦持ちをそのままアプリに触らせる

fact_measurement
-----------------------------
timestamp
metric_type
value

何が起きるか

  • 画面ごとに CASE 文量産
  • クエリの意図が読めない
  • バグ修正が怖い

👉 縦持ちは内部構造、外に出さない


アンチパターン③:意味の違うデータを縦持ちで混在させる

fact_measurement
-----------------------------
timestamp
metric_type
value
temperature = 実測 / 平均 / 最大

何が起きるか

  • 同じ metric_type なのに意味が違う
  • 集計すると意味破綻

👉 aggregation_type を持たない縦持ちは危険


アンチパターン④:万能な横持ち VIEW を作る

v_measurement_all
= 生データ + 時間集計 + 日次 + 月次

何が起きるか

  • VIEW が巨大化
  • パフォーマンス劣化
  • 利用者が前提を理解できない

👉 横持ち VIEW は用途限定が基本


アンチパターン⑤:縦持ち・横持ちを二者択一で考える

「縦持ちは正規化されていて正しい」
「横持ちはアンチパターン」

何が問題か

  • レイヤーの概念が消える
  • 設計議論が宗教戦争になる

👉 役割が違うだけで、優劣ではない


まとめ

  • 縦持ち・横持ちは対立概念ではない
  • 役割が違うだけ

縦持ち:事実に強い
横持ち:人間に優しい

計測データでは、
この2つを レイヤーで分ける
ことが重要です。


おわりに

縦持ち / 横持ちの話は、

  • UNION + VIEW
  • Read Model / Write Model
  • 集計データの扱い

と強くつながっています。

これらを一緒に考えると、
データ設計で迷うポイントがかなり減ります。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?