Turso vs DuckDB — 用途別選択ガイド【OLTP vs OLAP どっちを選ぶ?】
リアルタイム性の高いWebアプリケーションを構築したい。手元のデータを高速に分析したい。現代のデータ処理において、このような要望は多く聞かれます。TursoとDuckDBは、それぞれ異なる強みを持つデータベースです。
どちらのツールを選ぶべきか。この疑問は、プロジェクトの性質によって答えが変わります。この記事では、TursoとDuckDBのそれぞれの特徴を深く掘り下げます。OLTP(オンライントランザクション処理)とOLAP(オンライン分析処理)という視点から、あなたのプロジェクトに最適な選択肢を見つけるための判断基準を解説します。さらに、両者を組み合わせて使う場合の役割分担についても解説します。
一言で言うと
- Turso: リアルタイムアプリ向け分散SQLite
- DuckDB: 高速オンデマンド分析DB
比較表
TursoとDuckDBの主な違いを以下の表にまとめました。
| 項目 | Turso (libSQL) | DuckDB |
|---|---|---|
| 得意な処理 | OLTP (オンライントランザクション処理) | OLAP (オンライン分析処理) |
| 速度 | 低レイテンシの読み書きに最適化。エッジ配置。 | 分析クエリを高速実行。列指向、ベクトル化。 |
| 主要用途 | リアルタイムアプリ、サーバーレス、エッジDB | データ分析、ETL、ローカルでのデータ探索 |
| 基盤 | SQLite互換 (Rustで再実装された分散DB) | C++で実装された組み込み型分析DB |
| 機能 | 分散レプリカ、WebAssembly UDF、リモートアクセス、オフライン同期、SQLite互換。 | 高度なSQL、Python/R連携、CSV/Parquet直接読み込み、ウィンドウ関数、複雑な型。 |
| 学習コスト | SQLite知識があれば容易。分散DBの概念は別途学習。 | SQL知識があればすぐに使える。組み込み利用が直感的。 |
| インストール方法 | turso CLI でDB作成、接続。言語ごとのSDK。 | pip install duckdb (Python) など、多様な環境で手軽に導入。 |
| コミュニティ規模 | 新興だが活発。GitHub、Discordで成長中。 | 非常に大きく活発。多くのコントリビューター、言語バインディング。 |
| データモデル | 行指向 (SQLite互換) | 列指向 (分析に最適化) |
| スケーラビリティ | グローバル分散、エッジでのレプリケーション。 | ローカルリソースに依存。大規模データはメモリ・ディスク次第。 |
実際のコマンド比較
ここでは、それぞれのツールでの基本的な操作を比較します。
Turso: リアルタイムアプリのデータ管理
Tursoは、Webアプリケーションのバックエンドとして、ユーザーデータなどのトランザクション処理に適しています。
1. Turso CLIのインストールとデータベースの作成
まず、Turso CLIをインストールします。
curl -sSfL https://get.tur.so/install.sh | bash
次に、新しいデータベースを作成します。
turso db create my-app-db
作成したデータベースに接続するためのURLと認証トークンを取得します。
turso db show my-app-db --url
turso db tokens create my-app-db-token
これらの情報を使って、アプリケーションからデータベースに接続します。
2. Pythonでユーザーデータを操作する例
Pythonのlibsql-clientライブラリを使って、ユーザーデータを操作する例を示します。
まず、ライブラリをインストールします。
pip install libsql-client
Pythonスクリプトでデータベースに接続し、テーブルを作成し、データを挿入・検索します。
import os
from libsql_client import create_client
# 環境変数からデータベースURLとトークンを取得
# 例: export LIBSQL_URL="libsql://my-app-db-xxxx.turso.io"
# 例: export LIBSQL_AUTH_TOKEN="your_token_here"
url = os.environ.get("LIBSQL_URL")
auth_token = os.environ.get("LIBSQL_AUTH_TOKEN")
if not url or not auth_token:
print("LIBSQL_URL and LIBSQL_AUTH_TOKEN environment variables must be set.")
exit(1)
client = create_client(url=url, auth_token=auth_token)
async def main():
# テーブルを作成
await client.execute("DROP TABLE IF EXISTS users") # 既存のテーブルがあれば削除
await client.execute("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT UNIQUE)")
print("Table 'users' created.")
# データを挿入
await client.execute("INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com')")
await client.execute("INSERT INTO users (name, email) VALUES ('Bob', 'bob@example.com')")
print("Data inserted.")
# データを検索
result = await client.execute("SELECT * FROM users WHERE name = 'Alice'")
print("Search result for Alice:")
for row in result.rows:
print(f"ID: {row[0]}, Name: {row[1]}, Email: {row[2]}")
# 全てのデータを取得
all_users = await client.execute("SELECT * FROM users")
print("\nAll users:")
for row in all_users.rows:
print(f"ID: {row[0]}, Name: {row[1]}, Email: {row[2]}")
await client.close()
import asyncio
asyncio.run(main())
この例では、Tursoがアプリケーションのリアルタイムなデータ操作にどのように利用できるかを示しています。ユーザーの登録や情報の更新など、個別のトランザクションを高速に処理できます。
DuckDB: 大規模データの高速分析
DuckDBは、ローカル環境やサーバーで大規模なデータセットを分析するのに適しています。CSVやParquetファイルを直接読み込んで、複雑な分析クエリを実行できます。
1. DuckDBのインストール
Python環境でDuckDBをインストールします。
pip install duckdb pandas
pandasはデータフレーム操作に便利なので一緒にインストールします。
2. CSVファイルの読み込みと分析の例
架空の販売データsales_data.csvがあると仮定します。
date,product,region,sales_amount,quantity
2023-01-01,Laptop,East,1200,1
2023-01-01,Mouse,East,25,2
2023-01-02,Keyboard,West,75,1
2023-01-02,Laptop,Central,1100,1
2023-01-03,Mouse,East,25,2
2023-01-03,Monitor,West,300,1
2023-01-04,Laptop,East,1250,1
このCSVファイルをPythonで読み込み、分析します。
import duckdb
import pandas as pd
# 架空のCSVデータを作成 (実際にはファイルとして存在すると仮定)
csv_content = """date,product,region,sales_amount,quantity
2023-01-01,Laptop,East,1200,1
2023-01-01,Mouse,East,25,2
2023-01-02,Keyboard,West,75,1
2023-01-02,Laptop,Central,1100,1
2023-01-03,Mouse,East,25,2
2023-01-03,Monitor,West,300,1
2023-01-04,Laptop,East,1250,1
"""
with open("sales_data.csv", "w") as f:
f.write(csv_content)
# DuckDBに接続
con = duckdb.connect(database=':memory:', read_only=False)
# CSVファイルを直接読み込んで分析
print("--- 地域ごとの総売上 ---")
query_result = con.execute("""
SELECT
region,
SUM(sales_amount) AS total_sales
FROM 'sales_data.csv'
GROUP BY region
ORDER BY total_sales DESC;
""").fetchdf()
print(query_result)
print("\n--- 製品ごとの平均販売価格と販売数 ---")
query_result = con.execute("""
SELECT
product,
AVG(sales_amount / quantity) AS avg_price_per_unit,
SUM(quantity) AS total_quantity_sold
FROM 'sales_data.csv'
GROUP BY product
ORDER BY total_quantity_sold DESC;
""").fetchdf()
print(query_result)
# DuckDBを閉じる
con.close()
DuckDBは、外部ファイルを直接データソースとして扱える点が大きな特徴です。これにより、ETLプロセスの中間ステップや、手元でのデータ探索が非常に効率的になります。
こんな人にはTursoがおすすめ
- リアルタイム性の高いアプリケーションを開発している人: ユーザーのインタラクションに即座に反応するWebアプリやモバイルアプリのバックエンドに適しています。
- グローバルに分散したアプリケーションを構築したい人: エッジロケーションにデータベースのレプリカを配置し、ユーザーに近い場所から高速なデータアクセスを提供できます。
- サーバーレス環境でデータベースを利用したい人: Tursoはサーバーレス関数からの利用に最適化されており、スケーラビリティと運用負荷の低減を両立します。
- SQLiteのシンプルさを活かしつつ、スケールさせたい人: SQLiteの使い慣れたSQLとローカルDBの感覚を保ちながら、分散環境での可用性とパフォーマンスを実現します。
- オフライン対応のアプリケーションを考えている人: 双方向同期やエッジレプリカの機能は、オフラインでのデータ操作にも対応できます。
こんな人にはDuckDBがおすすめ
- 大規模データの高速な分析処理を行いたい人: 数GBから数TBのデータセットに対し、複雑な集計や結合クエリを高速に実行できます。
- PythonやRなどのデータ分析環境にデータベースを統合したい人: Pandasやdplyrといったライブラリと深く連携し、データフレームとSQLの間でシームレスな操作が可能です。
- ETL処理の中間ステップでデータを加工・集計したい人: CSVやParquetファイルなどの生データを直接読み込み、SQLで整形・変換する処理に強力な力を発揮します。
- ローカル環境で手軽にデータ探索やプロトタイピングを行いたい人: 外部サーバーのセットアップが不要で、すぐに分析を開始できるため、開発サイクルを短縮できます。
- クラウド環境に依存しないオフラインでのデータ分析が必要な人: 組み込み型データベースとして動作するため、インターネット接続がなくても分析作業を進められます。
両方使う場合の役割分担
TursoとDuckDBは、異なる得意分野を持つため、両方を組み合わせて利用することで、それぞれの強みを最大限に引き出せます。
Turso: アプリケーションのOLTP層
Tursoは、アプリケーションのユーザーが直接操作するデータを管理します。例えば、以下のようなデータです。
- ユーザーアカウント情報
- 注文履歴
- ブログ記事やコメント
- リアルタイムのセンサーデータ
これらのデータは、頻繁に読み書きされ、低レイテンシが求められます。Tursoは、エッジ配置されたレプリカにより、ユーザーに近い場所での高速なトランザクション処理を実現します。
DuckDB: 分析・レポート用のOLAP層
Tursoに蓄積されたOLTPデータは、そのままでは大規模な分析には向きません。そこで、Tursoから定期的にデータを抽出し、DuckDBにロードします。DuckDBでは、以下のような分析を実行できます。
- 日次、週次、月次の売上トレンド分析
- ユーザーの行動パターン分析(例: 特定機能の利用率、滞在時間)
- 地域別、製品別のパフォーマンス比較
- A/Bテストの結果分析
- 過去のデータに基づいた将来予測のための特徴量エンジニアリング
DuckDBは、これらの分析クエリを高速に実行し、データサイエンティストやアナリストに洞察を提供します。
具体的な連携フローの例
- Tursoへのデータ書き込み: アプリケーションがTursoにユーザー行動やトランザクションデータを記録します。
- データのエクスポート: Tursoから日次または時間単位でデータをエクスポートします。これは、Turso CLIの
turso db exportコマンドや、プログラムによるデータ抽出で実現できます。エクスポート形式はCSVやParquetが適しています。 - DuckDBへのデータロード: エクスポートされたCSV/ParquetファイルをDuckDBで読み込みます。DuckDBはこれらのファイルを直接クエリできるため、中間的なデータ変換は最小限で済みます。
- DuckDBでの分析: DuckDB上でSQLクエリを実行し、高度な分析やレポート作成を行います。結果はPandasデータフレームに変換して、さらにPythonで処理することも可能です。
このように、Tursoでリアルタイムのアプリケーションを支え、DuckDBでそのデータを深く分析することで、両者のメリットを最大限に活かしたデータ基盤を構築できます。
移行する場合の手順
ここでは、既存のTursoデータベースからDuckDBへデータを移行する基本的な手順を説明します。これは、Tursoで管理しているトランザクションデータを分析目的でDuckDBに取り込むシナリオを想定しています。
1. TursoデータベースからSQLダンプをエクスポートする
Turso CLIを使って、データベースの全データをSQLダンプとしてエクスポートします。これにより、テーブル構造とデータがSQL文としてファイルに保存されます。
# エクスポートしたいTursoデータベース名
DATABASE_NAME="my-app-db"
EXPORT_FILE="my_app_db_export.sql"
# データベースをSQLファイルにエクスポート
turso db export $DATABASE_NAME > $EXPORT_FILE
echo "Database '$DATABASE_NAME' exported to '$EXPORT_FILE'"
このmy_app_db_export.sqlファイルには、CREATE TABLE文とINSERT文が含まれます。
2. DuckDBでSQLダンプを読み込む
DuckDBはSQLファイルを直接読み込むことができます。Pythonクライアントを使用すると、簡単に実行できます。
import duckdb
# エクスポートしたSQLファイル名
EXPORT_FILE = "my_app_db_export.sql"
DUCKDB_DATABASE = "analysis.duckdb" # DuckDBの永続化ファイル (メモリDBの場合は ':memory:')
# DuckDBに接続 (永続化ファイルを作成する場合)
con = duckdb.connect(database=DUCKDB_DATABASE)
try:
# SQLファイルをDuckDBで実行
con.execute(f"IMPORT DATABASE '{EXPORT_FILE}';")
print(f"Successfully imported '{EXPORT_FILE}' into DuckDB database '{DUCKDB_DATABASE}'.")
# データの確認 (例: usersテーブルが存在する場合)
print("\n--- Users table content in DuckDB ---")
result = con.execute("SELECT * FROM users LIMIT 5;").fetchdf()
print(result)
except Exception as e:
print(f"Error during import: {e}")
finally:
con.close()
IMPORT DATABASEコマンドは、SQLファイルに含まれるテーブル作成とデータ挿入のSQL文を順次実行します。これにより、TursoのデータがDuckDBに再現されます。
3. CSV/Parquetとしてエクスポートし、DuckDBで読み込む (代替手段)
もしTursoからCSVやParquet形式でデータをエクスポートできる場合、DuckDBはこれらのファイルを直接読み込めるため、より効率的です。Turso自体に直接CSVエクスポート機能がない場合でも、Tursoからデータを取得し、プログラムでCSV/Parquetとして保存できます。
例えば、PythonでTursoからデータを取得し、CSVとして保存するシナリオを考えます。
import os
import csv
from libsql_client import create_client
# Turso接続情報
url = os.environ.get("LIBSQL_URL")
auth_token = os.environ.get("LIBSQL_AUTH_TOKEN")
async def export_turso_to_csv(table_name: str, output_csv_path: str):
client = create_client(url=url, auth_token=auth_token)
try:
result = await client.execute(f"SELECT * FROM {table_name}")
if not result.rows:
print(f"No data found for table '{table_name}'.")
return
# ヘッダーとデータをCSVファイルに書き込む
with open(output_csv_path, 'w', newline='', encoding='utf-8') as f:
writer = csv.writer(f)
writer.writerow(result.columns) # ヘッダーを書き込む
for row_data in result.rows:
writer.writerow(row_data) # データを書き込む
print(f"Table '{table_name}' exported to '{output_csv_path}'.")
except Exception as e:
print(f"Error exporting table '{table_name}': {e}")
finally:
await client.close()
import asyncio
asyncio.run(export_turso_to_csv("users", "users_data.csv"))
TursoからCSVファイルが生成されたら、DuckDBで直接読み込めます。
import duckdb
# DuckDBに接続
con = duckdb.connect(database=':memory:')
# CSVファイルを直接読み込む
print("\n--- Reading users_data.csv with DuckDB ---")
result = con.execute("SELECT * FROM 'users_data.csv' LIMIT 5;").fetchdf()
print(result)
# CSVファイルを基に集計を行う例
print("\n--- Counting users by email domain ---")
result_agg = con.execute("""
SELECT
SUBSTRING(email, INSTR(email, '@') + 1) AS domain,
COUNT(*) AS user_count
FROM 'users_data.csv'
GROUP BY domain
ORDER BY user_count DESC;
""").fetchdf()
print(result_agg)
con.close()
この方法では、DuckDBのファイル直接読み込みの強みを活かし、効率的に分析を開始できます。
まとめ
TursoとDuckDBは、現代のデータ処理において非常に強力なツールです。しかし、その用途は大きく異なります。
- Turso は、リアルタイム性の高いアプリケーションのバックエンドとして、低レイテンシのトランザクション処理とグローバルな分散配置に優れています。OLTPのニーズに応えます。
- DuckDB は、大規模なデータセットに対する高速な分析処理に特化しています。CSVやParquetファイルを直接読み込み、複雑なSQLクエリを効率的に実行できます。OLAPのニーズに応えます。
どちらか一方を選ぶだけでなく、両者を組み合わせて利用することで、アプリケーションのリアルタイム性とデータ分析の深度を両立できます。Tursoでアプリケーションデータを管理し、そのデータをDuckDBで分析するという役割分担は、多くのプロジェクトで有効なアプローチとなるでしょう。
あなたのプロジェクトの要件に合わせて、最適なツールを選択し、あるいは賢く連携させて活用してください。
関連ページ
参考文献
- Turso Documentation
- Turso GitHub Repository
- libSQL GitHub Repository
- DuckDB Documentation
- DuckDB GitHub Repository
- Python Client for libSQL
- DuckDB Python API
- Turso Blog: WebAssembly functions for your SQLite-compatible database
- DuckDB Blog: SQL on Pandas with DuckDB