Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
初心者アプリケーションエンジニアに向けたデータベース解説
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
yamotty
August 26, 2026
4
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
初心者アプリケーションエンジニアに向けたデータベース解説
yamotty
August 26, 2026
More Decks by yamotty
See All by yamotty
【株仙人の道】資産250億円の片山晃が教えるPER活用の極意
yamotty
0
90
国民負担の限界点
yamotty
0
63
日本の小売市場 日本の小売市場 構造変革と未来戦略
yamotty
0
48
製造業主導型経済からサービス経済化における中間層形成メカニズムのパラダイムシフト
yamotty
0
630
Featured
See All Featured
How Fast Is Fast Enough? [PerfNow 2025]
tammyeverts
3
820
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
56
3.4k
Fashionably flexible responsive web design (full day workshop)
malarkey
408
67k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
130k
Leveraging LLMs for student feedback in introductory data science courses - posit::conf(2025)
minecr
1
360
Pawsitive SEO: Lessons from My Dog (and Many Mistakes) on Thriving as a Consultant in the Age of AI
davidcarrasco
0
220
AI Search: Where Are We & What Can We Do About It?
aleyda
0
7.8k
How to train your dragon (web standard)
notwaldorf
97
6.8k
Bash Introduction
62gerente
615
220k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.8k
Bioeconomy Workshop: Dr. Julius Ecuru, Opportunities for a Bioeconomy in West Africa
akademiya2063
PRO
1
280
Public Speaking Without Barfing On Your Shoes - THAT 2023
reverentgeek
1
550
Transcript
初心者アプリケーションエンジニアに向けた データベース解説 アプリの品質と寿命を決めるのは、コードよりもデータベース 2026.08
コードは何度でも書き直せるが、データは書き直せない データの寿命はコードより長い フレームワークや実装は数年で入れ替わるが、スキーマとデータは10 年残り続ける アプリの本質はデータの入出力 寿命のイメージ UIコード 〜2年 画面もAPIも、突き詰めれば「データを正しく読み書きする」ための装 置にすぎない
バックエンド実装 設計ミスのやり直しコストが桁違い スキーマとデータ 3〜5年 10年以上 コードのリファクタは日単位、稼働中DBのスキーマ変更はデータ移行 を伴う月単位の仕事 ※ 一般的なWebサービスの目安 2
RDBは「型と制約でデータを守る」仕組みである テーブル = 同じ形をした事実の集合 1行が1つの事実(レコード)、列がその属性(カラム)を表す ordersテーブルの例 id customer_id total_price 1001
42 3,280 スキーマ = データの形の宣言 1002 17 980 各カラムの型・制約を先に決める。この「不自由さ」がデータ品質 を守る 1003 42 12,400 ← 1行 = 1件の注文という「事実」 Excelとの決定的な違いは「制約」 Excelは何でも入るが、RDBは不正なデータの混入をDB自身 が拒否できる スキーマの宣言例 (DDL) total_price INTEGER NOT NULL ordered_at TIMESTAMP NOT NULL 3
テーブル設計の出発点は「エンティティと関係」の抽出 エンティティ = 管理したいモノ・コト 顧客・商品のような「モノ」と、注文・支払のような「コト(イベン ト)」に分けて洗い出す 顧客 1 N 注文
1 関係は必ず「 1対多」に分解する 多対多は直接表現できないため、中間テーブル(注文明細)を 挟んで1対多×2に分解する N 商品 1 N 注文明細 この図がそのまま ER図になる 実装の前に紙に描く。ここでの手戻りはタダ、実装後の手戻り は高い 「注文と商品」の多対多は、注文明細を挟んで1対多×2に分解 4
正規化とは「同じ事実を一箇所にだけ書く」こと 重複した事実は、更新漏れ = 不整合の温床になる 顧客の住所を注文行ごとにコピーすると、住所変更のたびに全行を漏れなく更新する必要が生まれる Before: 注文に顧客情報を埋め込む After: 顧客テーブルに分離して参照する 注文ID
顧客名 住所 金額 注文ID 顧客ID 金額 1001 田中 豊中市… 3,280 1001 42 3,280 1002 鈴木 港区… 980 1003 42 12,400 1003 田中 豊中市… 12,400 顧客ID 顧客名 住所 42 田中 豊中市… 田中さんの引越し → 2行とも直す必要(直し漏れ=不整合) 住所変更は顧客テーブルの1行を直すだけで全注文に反映さ れる ※ 集計高速化などの目的で意図的に崩す(非正規化)こともあるが、まず正規形を知るのが先 5
守るべきルールは、アプリではなく DBに守らせる アプリのバグは必ず起きる。最後の砦を制約として DBに置く バリデーションはアプリにも書くが、複数のアプリやバッチが同じDBを触る以上、DB側の制約だけが全経路を守れる 主キー(PRIMARY KEY) 外部キー (FOREIGN KEY)
行を一意に特定するID。すべてのテーブルに必ず置く 存在しない親(顧客ID=999など)への参照をDBが拒否す る 一意制約 (UNIQUE) NOT NULL メールアドレスの重複登録などをDBレベルで防ぐ 「値がない」状態を許さない。NULLの扱いはバグの温床 6
よくあるアンチパターンは「あとで必ず高くつく」 1 カンマ区切りリスト tags = "a,b,c" のように1カラムに複数の値を詰め込 む 2 汎用カラム
col1, col2, ext_data, memo… 用途不明の入れ物 を用意する 3 検索・結合・集計が全滅する。中間テーブルに分解するのが正 解 意味が失われ、誰も削除も変更もできない負債になる 何でもVARCHAR 日付・数値・フラグを文字列型で保存する "2026/8/1" と "2026-08-01" が混在し、比較も集計も壊れる 7
インデックスは「本の索引」と同じ仕組み 索引がなければ全ページを読むしかない B-treeのイメージ インデックスのない検索 = フルスキャン。100万行なら100万行 すべてを確認する 50 B-treeで数ステップで目的の行へ 〜25
並び順を保った木構造を辿ることで、大きなテーブルでも一瞬で 行に到達できる 1..10 約20回 100万行のテーブルでも、 B-treeならこの程度の比較 回数で目的の行に到達 26〜50 26..38 51〜 39..50 80..99 WHERE id = 42 の探索経路(濃色)を上から辿るだけ ※ 代償: 書き込みのたびにインデックスも更新される (Slide 9) 8
インデックスは万能ではない。効く条件と代償を知る 効く 効かない / 代償あり WHERE での絞り込み 等値(=)や範囲(<, BETWEEN)の条件 先頭ワイルドカード検索
LIKE '%keyword' は並び順を使えずフルスキャンにな る JOIN の結合キー カラムへの関数適用 外部キーには基本的にインデックスを張る WHERE DATE(created_at) = … は索引を素通りする ORDER BY / ソート 値の種類が少ないカラム 並び順を保持しているためソートを省略できる 性別フラグなど絞り込み効果が薄いものは効きにくい 複合インデックスの左端から 書き込みコストの増加 INSERT / UPDATE のたびに索引も更新。張りすぎは 逆効果 (a, b) の索引は a 単独にも効くが、b 単独には効かない 目安: 「よく検索する条件に張る・むやみに増やさない」の2原則から始める 9
「遅い」は感覚ではなく、 EXPLAINで語る EXPLAINは「探し方」の答え合わせ クエリの前に EXPLAIN を付けるだけで、DBがどうデータを 探す計画かが見える MySQLでの例 EXPLAIN SELECT
* FROM orders WHERE customer_id = 42; 見るべきはまず 2つだけ アクセス方式(フルスキャンか索引か)と、読む行数の見積も り。この2つで大半は判断できる type: ALL rows: 1,203,441 ↓ customer_id にインデックスを追加 「張ったつもり」を検証できる 張ったのに使われないケース(関数適用・型不一致)は EXPLAINでしか気づけない type: ref rows: 12 読む行数が 120万 → 12 に。これが「インデックスが効い た」状態 10
N+1問題: ORMの便利さの裏で起きていること 「一覧100件の表示」が 101回のクエリになる 一覧の取得に1回 + ループの中で関連データを1件ずつ取得するN回。ORMを素朴に使うと簡単に発生する Before(N+1) orders =
Order.all orders.each do |o| o.customer.name end 100件の一覧 = 合計101クエリ After(まとめて取得 ) # 1回 # N回 orders = Order.includes(:customer) # SELECT * FROM orders # SELECT * FROM customers # WHERE id IN (42, 17, ..) 何件でも 合計2クエリ 対策の第一歩: 開発中はORMが発行するSQLをログに出し、目で見る習慣をつける 11
トランザクションは「途中で失敗」からデータを守る 「在庫は減ったのに決済は失敗」を起こさない仕組み 複数の更新をひとかたまり(トランザクション)にし、全部成功か全部なかったことにするかの二択にする A Atomicity(原子性) I Isolation(分離性) 処理は全部成功か、全部ロールバックか 同時実行のトランザクション同士が干渉しない C
Consistency(一貫性) D Durability(永続性) 制約を満たした状態だけが保存される コミットした結果は障害でも失われない まずはAtomicityを体で理解する。「注文確定処理をトランザクションで括る」が最初の一歩 12
学習は「手を動かす → 設計を学ぶ → 計測する」の順で 1 2 手を動かす SELECT /
JOIN / GROUP BY を 自分の手で書く。ORMの裏側の SQLを想像できるようになるのが目 標 SQL練習サイトや手元のサンプル DBで十分 → 3 設計を学ぶ 正規化・キー・アンチパターンを体系 的に。実務のテーブルをER図に描 き起こして答え合わせする 書籍: 「SQLアンチパターン」「達人 に学ぶDB設計 徹底指南書」 → 計測する EXPLAINとスロークエリログを日 常の道具にする。推測ではなく計測 で語れるようになる 本番相当のデータ量で試すことが 重要 3つを順に回すこと自体より、「実務の題材で試す」ことが定着の近道 13
まとめ: 明日からやること 3つ DBは一夜漬けできないが、毎日少しずつ触れるものでもある 以下の3つはどれも1〜2時間で始められて、効果を体感しやすい 1 自分のプロダクトの ER図を描いてみる 主要テーブル5〜10個で十分。説明できない関係 が学びの入口
2 ORMが発行する SQLをログで確認する N+1や無駄なクエリは、見えるようにした瞬間から 減り始める 3 一番遅い画面のクエリに EXPLAINをかける フルスキャンを1つ見つけてインデックスで直す。こ の成功体験が一番効く 14