最終更新:
Drizzle Studio実践ガイド: ブラウザベースのデータベースGUIとスキーマ管理
Drizzle Studio実践ガイド
Drizzle Studioは、Drizzle ORMに組み込まれたブラウザベースのデータベースGUIツールです。Prisma Studioのような視覚的なデータベース管理機能を提供しながら、軽量で高速に動作します。
本記事では、Drizzle Studioの実践的な使い方、データ操作、スキーマ管理、本番環境での活用まで詳しく解説します。
Drizzle Studioとは
主な機能
- ブラウザベースGUI - Webインターフェースでデータベースを視覚的に管理
- データ閲覧・編集 - テーブルデータのCRUD操作
- リレーション表示 - テーブル間の関連を視覚化
- SQLクエリ実行 - カスタムクエリの実行と結果表示
- スキーマビュー - データベース構造の可視化
- 複数DB対応 - PostgreSQL、MySQL、SQLite、Tursoをサポート
他のGUIツールとの比較
// Prisma Studio
// - 機能豊富だが重い
// - Prismaエコシステムに依存
// - バンドルサイズ大
// Drizzle Studio
// - 軽量で高速起動
// - Drizzle ORMに統合
// - エッジ環境でも動作可能
// - 設定ファイル不要
// 従来のGUIツール(TablePlus、DBeaver)
// - インストール必要
// - デスクトップアプリ
// - プロジェクト外のツール
セットアップ
基本インストール
# Drizzle ORMとDrizzle Kit(Studioを含む)
npm install drizzle-orm
npm install -D drizzle-kit
# データベースドライバー
npm install postgres # PostgreSQL
npm install @libsql/client # Turso
npm install mysql2 # MySQL
npm install better-sqlite3 # SQLite
Drizzle設定ファイル
// drizzle.config.ts
import type { Config } from 'drizzle-kit'
export default {
schema: './src/db/schema.ts',
out: './drizzle',
driver: 'pg',
dbCredentials: {
connectionString: process.env.DATABASE_URL!,
},
// Studio用の設定
verbose: true,
strict: true,
} satisfies Config
Studio起動
# デフォルトポート(4983)で起動
npx drizzle-kit studio
# カスタムポート指定
npx drizzle-kit studio --port 5555
# 特定の設定ファイル使用
npx drizzle-kit studio --config drizzle.config.prod.ts
# ブラウザが自動で開きます
# https://local.drizzle.studio
基本的な使い方
データベース接続
Drizzle Studioは drizzle.config.ts の設定を自動的に読み込みます。
// 開発環境
export default {
dbCredentials: {
connectionString: process.env.DATABASE_URL,
},
} satisfies Config
// 本番環境(読み取り専用)
export default {
dbCredentials: {
connectionString: process.env.DATABASE_URL_READONLY,
},
} satisfies Config
テーブルビュー
┌─────────────────────────────────────────┐
│ Tables │
├─────────────────────────────────────────┤
│ ☐ users (125 rows) │
│ ☐ posts (1,234 rows) │
│ ☐ comments (5,678 rows) │
│ ☐ categories (12 rows) │
└─────────────────────────────────────────┘
テーブルをクリックすると、データグリッドが表示されます。
データ閲覧
users テーブル
┌────┬──────────┬─────────────────────┬──────────┬──────────────────────┐
│ id │ name │ email │ role │ createdAt │
├────┼──────────┼─────────────────────┼──────────┼──────────────────────┤
│ 1 │ John Doe │ john@example.com │ admin │ 2025-01-01 10:00:00 │
│ 2 │ Jane Doe │ jane@example.com │ user │ 2025-01-02 11:30:00 │
│ 3 │ Bob │ bob@example.com │ user │ 2025-01-03 14:20:00 │
└────┴──────────┴─────────────────────┴──────────┴──────────────────────┘
機能:
- フィルタリング
- ソート(カラムヘッダークリック)
- ページネーション
- 検索
- 列の表示/非表示切り替え
データ操作
データ追加
1. テーブルビューで「+ Add Row」をクリック
2. フォームに入力:
Name: ────────────────────
Alice Smith
Email: ───────────────────
alice@example.com
Role: ────▼───────────────
user
[Cancel] [Save]
3. 「Save」で新しいレコード作成
フォームは、Drizzleスキーマ定義から自動生成されます。
// スキーマ定義
export const users = pgTable('users', {
id: serial('id').primaryKey(),
name: varchar('name', { length: 255 }).notNull(),
email: varchar('email', { length: 255 }).notNull().unique(),
role: roleEnum('role').default('user').notNull(),
bio: text('bio'), // optional
createdAt: timestamp('created_at').defaultNow(),
})
// Studioが自動的に:
// - 必須フィールドをバリデーション(notNull)
// - デフォルト値を設定(default)
// - Enumをドロップダウンで表示(pgEnum)
// - 自動生成フィールドを非表示(serial、defaultNow)
データ編集
1. 行をクリックして編集モード
┌─────────────────────────────────────┐
│ Edit User │
├─────────────────────────────────────┤
│ Name: [John Doe ] │
│ Email: [john@example.com ] │
│ Role: [admin ▼] │
│ Bio: [Software engineer ] │
│ [working on web apps ] │
│ │
│ Created: 2025-01-01 10:00:00 │
│ Updated: 2025-08-15 15:30:00 │
│ │
│ [Delete] [Cancel] [Save] │
└─────────────────────────────────────┘
2. フィールドを編集
3. 「Save」で変更を保存
データ削除
方法1: 編集モードから
- 行をクリック → 「Delete」ボタン
方法2: 一括選択
- 複数行にチェック → 「Delete Selected」
JSONフィールドの編集
// スキーマ定義
export const users = pgTable('users', {
id: serial('id').primaryKey(),
metadata: json('metadata').$type<{
preferences: {
theme: 'light' | 'dark'
language: string
}
settings: Record<string, any>
}>(),
})
// Studioでの編集
┌─────────────────────────────────────────┐
│ Metadata (JSON) │
├─────────────────────────────────────────┤
│ { │
│ "preferences": { │
│ "theme": "dark", │
│ "language": "ja" │
│ }, │
│ "settings": { │
│ "notifications": true, │
│ "email": "daily" │
│ } │
│ } │
├─────────────────────────────────────────┤
│ [Format] [Validate] [Collapse All] │
└─────────────────────────────────────────┘
- シンタックスハイライト
- 自動フォーマット
- JSONバリデーション
リレーション管理
1対多のリレーション
// スキーマ定義
export const users = pgTable('users', {
id: serial('id').primaryKey(),
name: varchar('name', { length: 255 }).notNull(),
})
export const posts = pgTable('posts', {
id: serial('id').primaryKey(),
title: varchar('title', { length: 255 }).notNull(),
authorId: integer('author_id').references(() => users.id),
})
export const usersRelations = relations(users, ({ many }) => ({
posts: many(posts),
}))
export const postsRelations = relations(posts, ({ one }) => ({
author: one(users, {
fields: [posts.authorId],
references: [users.id],
}),
}))
Studioでの表示:
users テーブル(id: 1)
┌────────────────────────────────────────┐
│ User Details │
├────────────────────────────────────────┤
│ ID: 1 │
│ Name: John Doe │
│ │
│ Posts (3) ▼ │
│ ┌─────────────────────────────────┐ │
│ │ • My First Post │ │
│ │ • Learn Drizzle ORM │ │
│ │ • Database Management Tips │ │
│ └─────────────────────────────────┘ │
│ │
│ [View Posts in Table] │
└────────────────────────────────────────┘
投稿をクリックすると、関連する投稿レコードへジャンプ
多対多のリレーション
// タグシステムの例
export const posts = pgTable('posts', {
id: serial('id').primaryKey(),
title: varchar('title', { length: 255 }),
})
export const tags = pgTable('tags', {
id: serial('id').primaryKey(),
name: varchar('name', { length: 100 }),
})
export const postsToTags = pgTable('posts_to_tags', {
postId: integer('post_id').references(() => posts.id),
tagId: integer('tag_id').references(() => tags.id),
})
export const postsRelations = relations(posts, ({ many }) => ({
postsToTags: many(postsToTags),
}))
export const tagsRelations = relations(tags, ({ many }) => ({
postsToTags: many(postsToTags),
}))
export const postsToTagsRelations = relations(postsToTags, ({ one }) => ({
post: one(posts, {
fields: [postsToTags.postId],
references: [posts.id],
}),
tag: one(tags, {
fields: [postsToTags.tagId],
references: [tags.id],
}),
}))
Studioでの表示:
posts テーブル(id: 5)
┌────────────────────────────────────────┐
│ Post: "Learn Drizzle ORM" │
├────────────────────────────────────────┤
│ Tags (3) ▼ │
│ ┌─────────────────────────────────┐ │
│ │ [×] TypeScript │ │
│ │ [×] Database │ │
│ │ [×] ORM │ │
│ │ │ │
│ │ [+ Add Tag] │ │
│ └─────────────────────────────────┘ │
└────────────────────────────────────────┘
- タグの追加/削除が可能
- 中間テーブル(postsToTags)は自動管理
フィルタリングとクエリ
基本フィルター
users テーブル
┌─────────────────────────────────────────┐
│ Filters │
├─────────────────────────────────────────┤
│ Role: [admin ▼] │
│ Status: [active ▼] │
│ Created: [Last 30 days ▼] │
│ │
│ [Apply] [Reset] │
└─────────────────────────────────────────┘
結果: 3 rows
高度な検索
┌─────────────────────────────────────────┐
│ Advanced Search │
├─────────────────────────────────────────┤
│ Field: [email ▼] │
│ Operator: [contains ▼] │
│ Value: [gmail.com ] │
│ │
│ [+ Add Condition] │
│ │
│ AND/OR: [AND ▼] │
│ │
│ Field: [role ▼] │
│ Operator: [equals ▼] │
│ Value: [user ▼] │
│ │
│ [Search] [Clear] │
└─────────────────────────────────────────┘
生成されるSQL:
SELECT * FROM users
WHERE email LIKE '%gmail.com%'
AND role = 'user';
カスタムSQLクエリ
-- SQLタブで直接クエリを実行
-- 投稿数の多いユーザーを取得
SELECT
u.id,
u.name,
COUNT(p.id) as post_count
FROM users u
LEFT JOIN posts p ON p.author_id = u.id
GROUP BY u.id, u.name
ORDER BY post_count DESC
LIMIT 10;
結果:
┌────┬──────────┬────────────┐
│ id │ name │ post_count │
├────┼──────────┼────────────┤
│ 5 │ Alice │ 45 │
│ 2 │ Jane │ 32 │
│ 1 │ John │ 28 │
└────┴──────────┴────────────┘
[Export CSV] [Export JSON]
スキーマ管理
スキーマビジュアライザー
┌─────────────────────────────────────────┐
│ Database Schema │
├─────────────────────────────────────────┤
│ │
│ ┌──────────┐ ┌──────────┐ │
│ │ users │────1:N──│ posts │ │
│ ├──────────┤ ├──────────┤ │
│ │ id │ │ id │ │
│ │ name │ │ title │ │
│ │ email │ │ authorId │ │
│ └──────────┘ └──────────┘ │
│ │ │ │
│ 1:N M:N │
│ │ │ │
│ ┌──────────┐ ┌──────────┐ │
│ │ comments │ │ tags │ │
│ ├──────────┤ ├──────────┤ │
│ │ id │ │ id │ │
│ │ content │ │ name │ │
│ │ userId │ └──────────┘ │
│ │ postId │ │
│ └──────────┘ │
│ │
│ [Export Schema] [Generate Diagram] │
└─────────────────────────────────────────┘
マイグレーション履歴
┌─────────────────────────────────────────┐
│ Migrations │
├─────────────────────────────────────────┤
│ ✓ 0001_initial_schema.sql │
│ Applied: 2025-01-01 10:00:00 │
│ │
│ ✓ 0002_add_user_roles.sql │
│ Applied: 2025-02-15 14:30:00 │
│ │
│ ✓ 0003_add_posts_table.sql │
│ Applied: 2025-05-20 09:15:00 │
│ │
│ ⊗ 0004_add_tags_system.sql (pending) │
│ │
│ [Run Pending] [Rollback] [Generate] │
└─────────────────────────────────────────┘
本番環境での活用
読み取り専用モード
// drizzle.config.prod.ts
import type { Config } from 'drizzle-kit'
export default {
schema: './src/db/schema.ts',
out: './drizzle',
driver: 'pg',
dbCredentials: {
// 読み取り専用レプリカを使用
connectionString: process.env.DATABASE_URL_READONLY!,
},
// Studio設定
studio: {
readOnly: true, // 編集を無効化
port: 4983,
},
} satisfies Config
起動:
# 本番DBを読み取り専用で閲覧
npx drizzle-kit studio --config drizzle.config.prod.ts
# データ閲覧・クエリ実行のみ可能
# INSERT/UPDATE/DELETEは無効化
SSHトンネル経由の接続
# 本番DBへのSSHトンネルを作成
ssh -L 5432:localhost:5432 user@production-server
# 別ターミナルでStudio起動
DATABASE_URL="postgresql://user:pass@localhost:5432/db" \
npx drizzle-kit studio
環境変数による切り替え
// drizzle.config.ts
import type { Config } from 'drizzle-kit'
const isDev = process.env.NODE_ENV === 'development'
export default {
schema: './src/db/schema.ts',
dbCredentials: {
connectionString: isDev
? process.env.DATABASE_URL_DEV!
: process.env.DATABASE_URL_READONLY!,
},
studio: {
readOnly: !isDev, // 本番は読み取り専用
},
} satisfies Config
チーム開発での活用
ローカル開発
# 各開発者のローカル環境
npm run db:studio
# package.json
{
"scripts": {
"db:studio": "drizzle-kit studio",
"db:studio:prod": "drizzle-kit studio --config drizzle.config.prod.ts"
}
}
ステージング環境
# docker-compose.yml
version: '3.8'
services:
db:
image: postgres:16
ports:
- "5432:5432"
environment:
POSTGRES_DB: myapp
POSTGRES_USER: dev
POSTGRES_PASSWORD: devpass
studio:
image: node:20
working_dir: /app
volumes:
- .:/app
ports:
- "4983:4983"
command: npx drizzle-kit studio --host 0.0.0.0
depends_on:
- db
environment:
DATABASE_URL: postgresql://dev:devpass@db:5432/myapp
起動:
docker-compose up studio
# チーム全員が http://localhost:4983 でアクセス可能
トラブルシューティング
接続エラー
// エラー: Could not connect to database
// 解決策1: 接続文字列を確認
console.log(process.env.DATABASE_URL)
// 解決策2: データベースが起動しているか確認
// PostgreSQLの場合
psql -U postgres -c "SELECT version();"
// 解決策3: ファイアウォール・ネットワーク設定
// ローカルDBの場合、localhost or 127.0.0.1を使用
スキーマ同期エラー
# エラー: Schema out of sync
# 解決策: マイグレーションを実行
npx drizzle-kit push:pg
# または、マイグレーションファイル生成
npx drizzle-kit generate:pg
npx tsx src/db/migrate.ts
パフォーマンス問題
// 大量データのテーブルが遅い場合
// 解決策1: ページネーション設定
export default {
studio: {
pagination: {
default: 50, // デフォルト表示件数
max: 500, // 最大表示件数
},
},
} satisfies Config
// 解決策2: インデックス追加
export const users = pgTable('users', {
id: serial('id').primaryKey(),
email: varchar('email', { length: 255 }).notNull(),
}, (table) => ({
emailIdx: index('email_idx').on(table.email),
}))
ベストプラクティス
1. 開発環境でのみ使用
// 本番環境では読み取り専用モードか、完全に無効化
if (process.env.NODE_ENV === 'production') {
// Studioを起動しない
} else {
// 開発環境のみ起動
execSync('drizzle-kit studio')
}
2. データベース接続の管理
// 環境ごとに異なる接続文字列
const configs = {
development: process.env.DATABASE_URL_DEV,
staging: process.env.DATABASE_URL_STAGING,
production: process.env.DATABASE_URL_READONLY, // 読み取り専用
}
3. スキーマファイルの整理
// 大規模プロジェクトではスキーマを分割
// src/db/schema/users.ts
export const users = pgTable('users', {...})
export const usersRelations = relations(users, {...})
// src/db/schema/posts.ts
export const posts = pgTable('posts', {...})
export const postsRelations = relations(posts, {...})
// src/db/schema/index.ts
export * from './users'
export * from './posts'
// drizzle.config.ts
export default {
schema: './src/db/schema/index.ts',
} satisfies Config
まとめ
Drizzle Studioは、以下の点で優れたデータベースGUIツールです。
主な利点
- 軽量で高速 - Prisma Studioより起動が速い
- 設定不要 - drizzle.config.tsがあればすぐ使える
- 統合性 - Drizzle ORMとシームレスに連携
- 柔軟性 - 開発から本番まで様々な環境で利用可能
使い分け
// 開発環境
// - フル機能で使用
// - データ作成・編集・削除
// ステージング環境
// - チームでの共有
// - テストデータ確認
// 本番環境
// - 読み取り専用モード
// - デバッグ・調査用途のみ
Drizzle Studioを活用することで、データベース操作が視覚的かつ効率的になり、開発体験が大幅に向上します。