理論から学ぶデータベース実践入門 リレーショナルモデルによる効率的なSQL
理論から学ぶデータベース実践入門 ~リレーショナルモデルによる効率的なSQL (WEB+DB PRESS plus)
技術評論社
目次
はじめに
第1章 SQLとリレーショナルモデル
1.1 そもそもSQLって?
リレーショナルモデルを知らなくてもSQLは書ける?
RDBはリレーショナルモデルを正しく実践してこそ真価を発揮する!
1.2 リレーショナルモデル
リレーションの定義
集合とリレーショナルモデル
集合とは
リレーショナルモデルとNULL
有限集合と無限集合
リレーションの演算
制限(Restrict)
射影(Projection)
拡張(Extend)
属性名変更(Rename)
和(Union)
積/交わり(Intersect)
差(Difference)
直積(Product)
結合(Join)
コラム 要素にNULLが含まれていると……
クロージャという性質
リレーショナルモデルにおけるデータ型
データ型と変数
ドメインとは
1.3 SQLにおけるリレーション操作
SELECTの基本形
コラム 拡張の評価順
INSERT(挿入)
コラム Relvar
DELETE(削除)
UPDATE(更新)
1.4 SQLにあってリレーショナルモデルにないもの
要素の重複
要素間の順序
リレーションの更新
トランザクション
ストアドプロシージャ
NULL
1.5 まとめ
コラム リレーショナルモデルは古典的か
第2章 述語論理とリレーショナルモデル
2.1 述語論理とリレーショナルモデル
命題
命題論理
結合子
真理関数の真理値
トートロジーと定理
トートロジー
トートロジー=定理
命題論理と公理系
公理
公理系のサンプル
背理法についての追記
公理系を用いた証明のコツ
きわめて厄介なPrinciple of explosion
コラム プリミティブな演算子
命題論理の限界と量化
命題論理の限界
量化
量化子と述語論理
述語論理
量化子とともに用いる束縛変数
量化子を伴わない自由変数
述語論理と集合論
述語と集合は等価に置き換えが可能
集合の包含関係
集合と要素の包含関係の違い
述語論理の公理系
述語論理の公理系の導出規則
ドメイン
一階述語論理
二階述語論理
リレーションの真の姿
リレーションの演算は論理演算
閉世界仮説
矛盾したDBは役に立たない
コラム リレーショナルモデルの限界
2.2 リレーションの演算と述語論理
制限(Restrict)
直積(Product)
結合(Join)
積(Intersect)
コラム 結合と制限
和(Unoin)
差(Difference)
射影(Projection)
属性名変更(Rename)
拡張(Extend)
コラム 外部結合について
2.3 まとめ
第3章 正規化理論(その1)―― 関数従属性 ――
3.1 なぜDB設計は重要なのか
3.2 正規化
リレーショナルモデルを補完する理論
異常を防ぐことができる
異常が生じた例
リレーションの設計が常識的におかしい
なぜ異常が起きるのか
異常を起こす原因は重複
3.3 正規形
正規形の種類
第1正規形(1NF)
カラムや行の順序
重複する行をなくす
NULLが含まれてはいけない
値のアトミック性
コラム 列の値はスカラであるべき?
繰り返しグループ
候補キーとスーパーキー
関数従属性(FD)
第2正規形(2NF)
無損失分解
第3正規形(3NF)
ボイスコッド正規形(BCNF)
コラム 候補キー内部に自明ではない関数従属性は存在しないのか
3.4 まとめ
第4章 正規化理論(その2)―― 結合従属性 ――
4.1 結合従属性(JD)
結合従属性は無損失分解が可能
関数従属性は結合従属性の一種である
暗黙的な結合従属性
非キー属性と結合従属性
コラム なぜ非キー属性があると,候補キーを無損失分解可能な結合従属性が存在しないのか
4.2 結合従属性による正規化(4NF~6NF)
第4正規形(4NF)
第5正規形(5NF)
接続の罠
直積と結合従属性
結合従属性を発見するのは難しい?
第6正規形(6NF)
4.3 まとめ
第5章 リレーションの直交性
5.1 リレーションの直交性と重複
レプリカ
同じ型を含むリレーション
見出しの一部だけが同じリレーション
5.2 リレーション直交化のための戦略
正規化
属性(カラム)の名前を統一する
命名規則を統一する
主語を含める
アプリケーションの整合性
すべてを直交化する必要はない
5.3 重複を解消することのメリット
異常を防げる
必要なデータがどこにあるかが明確になる
クエリの記述が宣言的になる
不要な無損失分解が必要ない
複雑な制約が必要ない
アプリケーションのコードに無駄がなくなる
性能が向上する
5.4 まとめ
第6章 ドメインの設計戦略
6.1 ドメイン
ドメインとは
集合の要素
6.2 ドメインの設計戦略の概要
すべては恣意的な選択
アプリケーションの要求から生まれる
適切なDB設計に必要なこと
ドメイン駆動設計
DBのリファクタリング
データの本質を見極める
数値に文字列カラムを割り当てる例
DBは本質的なデータを扱うようにする
属性(カラム)の名前
6.3 IDを設計するという考え方
現実世界の物体や概念を表す手段
ナチュラルキーとサロゲートキー
どちらを使うべきか
ナチュラルキーの使いどころと問題点
サロゲートキーの使いどころと問題点
リレーショナルモデルにおけるキー
意味を含んだID
コラム 紙の呪縛
IDの欠陥は波及する
色,長さ,重さなどの性質を表す属性
6.4 SQLによるドメインの表現
適切なデータ型を選ぶ
述語を制約で表現する
ドメインをテーブルとして表現する
6.5 まとめ
第7章 NULLとの戦い
7.1 NULL
NULLとは
3値論理(3VL)
NULLは演算を台無しにする
検索結果が意図しないものになる可能性
NULLによる第3の論理値
想像以上に厄介な3VL
3値論理の限界
Unknownと曖昧さ
コラム 量子コンピュータとNULL
NULLは閉世界仮説に反する
オプティマイザへの弊害
7.2 NULL対策
テーブルを正規化する
誤ったNULL対策
COALESCE関数
空文字列の扱い
NULLを使っても良いケース
7.3 まとめ
第8章 SELECTを攻略する
8.1 SELECTはSQLの心臓部
SELECTの本質
SELECTの強大さ
データを取得する唯一の手段
SELECTの基本構造
8.2 SELECT七変化
集約関数
関数の有無だけで意味が変わる
COUNTの特殊性
GROUP BYによる集約の書式
サブクエリ
テーブルサブクエリ
スカラサブクエリ
行サブクエリ
ビュー
UNION
組み合わせは自由
8.3 リレーショナルではない操作
リレーショナルな操作のおさらい
ソート
明示的に定義されていないカラム
ストアドファンクション(ユーザ定義関数)
コラム 集約とGROUP BY
リレーショナルではない操作の扱い方
8.4 インデントでSELECT文を読みやすくする
インデントのルール
8.5 まとめ
第9章 履歴データとうまく付き合う
9.1 履歴データの問題点
世界は履歴データで溢れている
履歴とリレーショナルモデルの相性問題
履歴データの具体例
履歴データの何が問題になるのか
リレーションと時間軸の直交性
NULLの可能性
特定の行だけ意味が違う
9.2 履歴データに対する解決策
リレーションを分割する
最もシンプルな分割方法
外部キーが使用できない
2つのテーブルの整合性
重複した行を許容する
サロゲートキー
未来の価格はどうすべきか
9.3 履歴データのアンチパターン
フラグを立てる
コラム フラグのお化け
手続き型として実装する
コラム テーブルを分けたときの物理的なメリット
9.4 まとめ
第10章 グラフに立ち向かう
10.1 グラフの構造
ノード,エッジ
隣接
次数
歩道,小道,道
多重辺
ループ
閉路
連結
部分グラフ
カットセット,ブリッジ
エッジの向きと重み
グラフの応用例
10.2 グラフの種類
一般グラフ
単純グラフ
連結グラフ/非連結グラフ
完全グラフ
正則グラフ
平面グラフ
有向グラフ/無向グラフ
重み付きグラフ
ツリー(木)
10.3 SQLとグラフの相性問題
グラフに対するクエリ
無向グラフを表現できるか
有向グラフを用いた表現
リレーショナルな視点でモデルを理解する
行列を用いた表現
グラフに対するクエリ
手続き型による解法
グラフDB
コラム FlockDB
そのほかの問題
10.4 ツリー(木)
ツリーはグラフの一種
コラム ディレクトリのハードリンクが作成できない理由
隣接リストモデル
NULLが許容される理由
経路列挙モデル
入れ子集合モデル
入れ子集合をテーブルで表現する
リレーショナルモデルと相性が悪い理由
クロージャテーブル
ツリーとSQLに関する考察
10.5 まとめ
第11章 インデックスの設計戦略
11.1 インデックスの働き
RDBのインデックス
インデックスの左端と範囲検索
セカンダリインデックスの更新
11.2 インデックスの種類
ハッシュインデックス
全文検索インデックス
形態素解析
Nグラム
Rツリーインデックス
関数インデックス
ビットマップインデックス
コラム クラスタインデックス
11.3 パーティショニング
パーティショニングとは
パーティショニングが適しているケース
パーティショニングと一意性制約
パーティショニングについてよくある誤解
11.4 リレーショナルモデルとインデックス
インデックスはリレーショナルモデルの一部ではない
正規化とインデックス
カラム数が絞られる
問題児NULL
11.5 指令:最適なインデックスを探せ!
必要なインデックス
インデックスのアクセス特性
インデックスが使用される構文
WHERE句
JOIN
相関サブクエリ
ソート
カヴァリングインデックス
ORとインデックス
最適なインデックスを探すための戦略
インデックス ≠ 候補キー
カラムの並び順
カーディナリティ
最適な組み合わせを探す
難しい作業に立ち向かう
真の最適解にこだわらない
コラム こんなインデックス設計はゴミ箱行きだ!
11.6 まとめ
第12章 Webアプリケーションのためのデータ構造
12.1 キャッシュという考え方
メリット/デメリット
メリット
デメリット
DBアプリケーションにおけるキャッシュ
キャッシュはあくまでもキャッシュ
キャッシュとして使うための要件
キャッシュすべきデータの種別
キャッシュすべきではないデータ
キャッシュが可能なデータ
12.2 キャッシュの実装方法
NoSQLをキャッシュとして使う
論理データはRDBで管理する
データ同期の際の注意点
コラム NoSQLでRDBは置き換えられるか?
テーブルをキャッシュとして使う
集計テーブル
結合済みのデータ
ディスクI/Oを削減できる
ソートとの相性が良い
NewSQLとの相性が良い
タグ
コラム 転置インデックスを使用して検索を高速化する
12.3 スケールアウト
レプリケーション
レプリケーションのしくみ
スレーブへの問い合わせ方式
データの論理的整合性と非同期レプリケーション
シャーディング
シャーディングのしくみ
シャーディングの最大の問題点
NoSQLのシャーディング
12.4 まとめ
第13章 リファクタリングの最適解
13.1 リファクタリング
DBのリファクタリングは大変
マルチアプリケーションにおけるDB環境
なぜリファクタリングが必要なのか
リファクタリングの手順
スキーマの移行期間
反復的なリファクタリング
回帰テスト
ベンチマークテスト
マイグレーション利用のススメ
トリガーを使って2つのテーブル間で同期を取る
13.2 リファクタリングの種類
インデックスの追加・削除
カラム名の変更
NOT NULL制約の導入
主キーの定義変更
無損失分解
テーブルの垂直分割と統合
コラム 関連テーブルの実態
13.3 リファクタリングのためのベストプラクティス
正規化と直交性
カラムではなくテーブルを追加する
SELECT * を使わない
アプリケーションを疎結合に
13.4 まとめ
第14章 トランザクションの本質
14.1 トランザクション
トランザクションの機能
同時実行制御
クラッシュリカバリ
トランザクションの鍵,スケジュール
処理の並列化は必要不可欠
同時自動制御の鍵,スケジュール
「データの正しさ」の定義
スケジューラの性能
14.2 トランザクションの特徴
ACIDとは
原子性(Atomicity)
一貫性(Consistensy)
分離性(Isolation)
永続性(Durability)
さまざまな異常
ロストアップデート
インコンシステントリード
ダーティリード
ノンリピータブルリード
ファントムリード
スケジュールとロック
デッドロック
トランザクションの分離レベル
MVCC
クラッシュリカバリ
DBサーバのコンポーネント
14.3 トランザクションとデータモデルの融合
リレーショナルモデルとACIDの「C」
リレーショナルモデルと異常
正規化と直交性
制約
データモデルだけでは不十分である理由
制約を活用してデータを守る
NOT NULL
一意制約
CREATE TYPE
CHECK制約
外部キー制約
トリガー
14.4 まとめ
おわりに
索引
著者プロフィール