はじめに
データベースの世界でよく登場する OLTP と OLAP という2つの用語。どちらも「Online」から始まりますが、目的も設計思想もまったく異なります。
この記事では、OLTPとOLAPの違いを具体例を交えて解説し、Snowflakeのテーブル形式との関係についても触れます。
ひとことで言うと
- OLTP(Online Transaction Processing) = 日々の業務を「処理する」ためのワークロード
- OLAP(Online Analytical Processing) = 蓄積されたデータを「分析する」ためのワークロード
比較表
| 観点 | OLTP | OLAP |
|---|---|---|
| 目的 | 業務処理(注文・振込・更新) | データ分析(集計・レポート・予測) |
| 操作の特徴 | 少量の行を高頻度で読み書き | 大量の行をまとめて読み取り |
| レイテンシ要件 | ミリ秒単位 | 秒〜分単位でも許容 |
| 同時接続数 | 非常に多い(数千〜数万) | 比較的少ない(数十〜数百) |
| データ量(1回の操作) | 数行〜数十行 | 数百万〜数億行 |
| データの鮮度 | リアルタイム | バッチ更新(数分〜数時間遅延) |
| データ形式 | 行指向が有利 | 列指向が有利 |
| 整合性 | 厳密(ACID必須) | 結果整合性でも許容されることが多い |
| 代表的な製品 | MySQL, PostgreSQL, Oracle | Snowflake, BigQuery, Redshift |
OLTPを詳しく見る
どんな処理?
OLTPは、ユーザーが行う 1件1件の操作(トランザクション) を正確かつ高速に処理するワークロードです。
身近な例を挙げると、以下のような処理がすべてOLTPです。
- ECサイトで商品を購入する
- 銀行アプリで口座間の振込を行う
- 予約システムで空席を確認して予約を確定する
- SNSに投稿する
典型的なSQL
-- 1件の注文を登録
INSERT INTO orders (user_id, product_id, quantity, order_date)
VALUES (12345, 67890, 2, CURRENT_TIMESTAMP());
-- 在庫を減らす
UPDATE inventory
SET stock = stock - 2
WHERE product_id = 67890;
-- 特定ユーザーの注文を取得
SELECT * FROM orders WHERE user_id = 12345;
ポイントは、WHERE句で 特定の行をピンポイントに 操作していることです。
なぜ「行指向」が有利なのか
OLTPでは1つのレコードの全カラムをまとめて読み書きすることが多いため、行指向ストレージ(1行のデータを連続して格納する方式)が効率的です。
行指向ストレージのイメージ:
[Row1: id=1, name="田中", email="tanaka@...", age=30]
[Row2: id=2, name="鈴木", email="suzuki@...", age=25]
[Row3: id=3, name="佐藤", email="sato@...", age=35]
↑ 1行まるごと読み書きしやすい
OLAPを詳しく見る
どんな処理?
OLAPは、大量のデータを 横断的に集計・分析 するワークロードです。
- 「先月の売上を地域別・商品カテゴリ別に集計したい」
- 「過去3年間の顧客離脱率のトレンドを可視化したい」
- 「広告キャンペーンごとのROIを比較したい」
これらはすべてOLAPの処理にあたります。
典型的なSQL
-- 地域別・月別の売上集計
SELECT
region,
DATE_TRUNC('month', order_date) AS month,
SUM(amount) AS total_sales,
COUNT(DISTINCT user_id) AS unique_customers
FROM orders
JOIN customers USING (customer_id)
WHERE order_date >= '2025-01-01'
GROUP BY region, month
ORDER BY month, total_sales DESC;
ポイントは、大量の行を読み取り、GROUP BYで集計していることです。特定のカラム(region、order_date、amount、user_id)しか使っていない点にも注目してください。
なぜ「列指向」が有利なのか
OLAPでは、全カラムではなく 必要なカラムだけ を大量の行から読み取ることが多いため、列指向ストレージ(同じカラムのデータを連続して格納する方式)が効率的です。
列指向ストレージのイメージ:
[name列: "田中", "鈴木", "佐藤", ...]
[email列: "tanaka@...", "suzuki@...", "sato@...", ...]
[age列: 30, 25, 35, ...]
↑ 必要なカラムだけ読めばよいので高速
↑ 同じ型のデータが並ぶため圧縮率も高い
OLTPとOLAPの従来の関係
従来、OLTPとOLAPは 別々のシステム で運用されるのが一般的でした。
この構成には以下のような課題があります。
- データの遅延: ETLパイプラインのスケジュールに依存し、リアルタイム性が失われる
- 運用の複雑さ: 2つの異なるシステムを管理・監視する必要がある
- データの不整合: パイプラインの障害やタイミングのずれで、分析データと業務データに差異が生じる
Snowflakeのテーブル形式との関係
ここで、前回の記事で解説した3つのテーブル形式がどのように関わるかを見てみましょう。
Snowflakeテーブル → OLAP特化
Snowflakeテーブルは 列指向フォーマット(マイクロパーティション)でデータを格納するため、大量データの集計・分析クエリに最適化されています。まさにOLAPのためのテーブルです。
-- Snowflakeテーブルが得意とする処理
SELECT
product_category,
SUM(sales_amount) AS total_sales
FROM fact_sales -- 数億行のファクトテーブル
GROUP BY product_category;
ハイブリッドテーブル → OLTPとOLAPの統合(Unistore)
ハイブリッドテーブルは 行ストア(OLTP向き)と オブジェクトストレージ(OLAP向き)の両方を内部に持ちます。書き込みは行ストアに直接入り、非同期でオブジェクトストレージにコピーされます。Snowflakeのクエリオプティマイザが、クエリの種類に応じてどちらから読み取るかを自動で判断します。
-- OLTP的な操作: 単一行の高速検索・更新
SELECT * FROM users WHERE user_id = 12345;
UPDATE users SET last_login = CURRENT_TIMESTAMP() WHERE user_id = 12345;
-- OLAP的な操作: 同じテーブルに対して集計も可能
SELECT
DATE_TRUNC('month', created_at) AS month,
COUNT(*) AS new_users
FROM users
GROUP BY month;
これにより、従来のOLTP→ETL→OLAPという データの移動を省略 できる可能性があります。Snowflakeはこのアプローチを Unistore と呼んでいます。
ただし、ハイブリッドテーブルがすべてのOLTPワークロードを置き換えられるわけではありません。専用のRDBMS(PostgreSQL等)と比べると、トランザクション処理の機能や成熟度にはまだ差があります。現時点では、比較的シンプルなトランザクション要件と分析要件を1つのプラットフォームで扱いたい場合に最も効果的です。
まとめ
| OLTP | OLAP | |
|---|---|---|
| ひとことで | 業務を「処理する」 | データを「分析する」 |
| データの扱い方 | 少量を高速に読み書き | 大量をまとめて読み取り |
| 有利なストレージ | 行指向 | 列指向 |
| Snowflakeでは | ハイブリッドテーブル | Snowflakeテーブル / Icebergテーブル |
従来はOLTPとOLAPは完全に別のシステムでしたが、Snowflakeのハイブリッドテーブル(Unistore)のように、両者を統合しようとする動きが進んでいます。とはいえ万能ではないので、要件に応じた使い分けが引き続き重要です。