目次
- はじめに
- 謝辞
- サンプルコードのダウンロード
- 本書の構成
第1章 DBMSのアーキテクチャ──この世にただ飯はあるか
1.1 DBMSのアーキテクチャ概要
- クエリ評価エンジン
- バッファマネージャ
- ディスク容量マネージャ
- トランザクションマネージャとロックマネージャ
- リカバリマネージャ
1.2 DBMSとバッファ
- この世にただ飯はあるか
- DBMSと記憶装置の関係
- HDD
- メモリ
- バッファの活用による速度向上
- メモリ上の2つのバッファ
- データキャッシュ
- ログバッファ
- メモリの性質がもたらすトレードオフ
- 揮発性とは
- 揮発性の問題点
- システムの特性によるトレードオフ
- データキャッシュとログバッファのサイズ
- 検索と更新,大事なのはどっち
- もう一つのメモリ領域「ワーキングメモリ」
- いつ使われるか
- 不足すると何が起きるのか
1.3 DBMSと実行計画
- 権限委譲の功罪
- データへのアクセス方法はどう決まるのか
- パーサ(parser)
- オプティマイザ(optimizer)
- カタログマネージャ(catalog manager)
- プラン評価(plan evaluation)
- オプティマイザとうまく付き合う
- 適切な実行計画が作成されるようにするには
1.4 実行計画がSQL文のパフォーマンスを決める
- 実行計画の確認方法
- テーブルフルスキャンの実行計画
- 操作対象のオブジェクト
- オブジェクトに対する操作の種類
- [Column]実行計画の「実行コスト」と「実行時間」
- 操作の対象となるレコード数
- インデックススキャンの実行計画
- 操作の対象となるレコード数
- 操作対象のオブジェクトと操作
- 簡単なテーブル結合の実行計画
- オブジェクトに対する操作の種類
1.5 実行計画の重要性
第1章のまとめ
演習問題1
- [Column]いろいろなキャッシュ
第2章 SQLの基礎──母国語を話すがごとく
2.1 SELECT文
- SELECT句とFROM句
- WHERE句
- WHERE句のさまざまな条件指定
- WHERE句は巨大なベン図
- INでOR条件を簡略化する
- NULL──何もないとはどういうことか
- [Column]SELECT文は手続き型言語の関数
- GROUP BY句
- グループ分けするメリット
- ホールケーキを全部1人で食べたい人は?
- HAVING句
- ORDER BY句
- ビューとサブクエリ
- ビューの作り方
- 無名のビュー
- サブクエリを使った便利な条件指定
2.2 条件分岐,集合演算,ウィンドウ関数,更新
- SQLと条件分岐
- CASE式の構文
- CASE式の動作
- SQLで集合演算
- UNIONで和集合を求める
- INTERSECTで積集合を求める
- EXCEPTで差集合を求める
- ウィンドウ関数
- トランザクションと更新
- INSERTでデータを挿入する
- DELETEでデータを削除する
- UPDATEでデータを更新する
第2章のまとめ
演習問題2
第3章 SQLにおける条件分岐──文から式へ
3.1 UNIONを使った冗長な表現
- UNIONによる条件分岐の簡単なサンプル
- UNIONを使うと実行計画が冗長になる
- UNIONを安易に使うべからず
- WHERE句で条件分岐させるのは素人
- SELECT句で条件分岐させると実行計画もすっきり
3.2 集計における条件分岐
- 集計対象に対する条件分岐
- UNIONによる解
- UNIONの実行計画
- 集計における条件分岐もやはりCASE式
- CASE式の実行計画
- 集約の結果に対する条件分岐
- UNIONで条件分岐させるのは簡単だが……
- UNIONの実行計画
- CASE式による条件分岐
- CASE式による条件分岐の実行計画
3.3 それでもUNIONが必要なのです
- UNIONを使わなければ解けないケース
- UNIONを使ったほうがパフォーマンスが良いケース
- UNIONによる解
- ORを使った解
- INを使った解
3.4 手続き型と宣言型
- 文ベースと式ベース
- 宣言型の世界へ跳躍しよう
第3章のまとめ
演習問題3
第4章 集約とカット──集合の世界
4.1 集約
- 複数行を1行にまとめる
- CASE式とGROUP BYの応用
- 集約・ハッシュ・ソート
- 合わせ技1本
4.2 カット
- あなたは肥り過ぎ? 痩せ過ぎ? ──カットとパーティション
- パーティション
- BMIによるカット
- PARTITION BY句を使ったカット
第4章のまとめ
演習問題4
第5章 ループ──手続き型の呪縛
5.1 ループ依存症
- Q.「先生,なぜSQLにはループがないのですか?」
- A.「ループなんてないほうがいいな,と思ったからです」
- それでもループは回っている
5.2 ぐるぐる系の恐怖
- ぐるぐる系の欠点
- SQL実行のオーバーヘッド
- 並列分散がやりにくい
- データベースの進化による恩恵を受けられない
- ぐるぐる系を速くする方法はあるか
- ぐるぐる系をガツン系に書き換える
- 個々のSQLを速くする
- 処理を多重化する
- ぐるぐる系の利点
- 実行計画が安定する
- 処理時間の見積り精度が(相対的には)高い
- トランザクション制御が容易
5.3 SQLではループをどう表現するか
- ポイントはCASE式とウィンドウ関数
- [Column]相関サブクエリによる対象レコードの制限
- ループ回数の上限が決まっている場合
- 近似する郵便番号を求める
- ランキングの問題に読み替え可能
- ウィンドウ関数でスキャン回数を減らす
- [Column]インデックスオンリースキャン
- ループ回数が不定の場合
- 隣接リストモデルと再帰クエリ
- 入れ子集合モデル
5.4 バイアスの功罪
第5章のまとめ
演習問題5
第6章 結合──結合を制する者はSQLを制す
6.1 機能から見た結合の種類
- クロス結合──すべての結合の母体
- [Column]自然結合の構文
- クロス結合の動作
- クロス結合が実務で使われない理由
- うっかりクロス結合
- 内部結合──何の「内部」なのか
- 内部結合の動作
- 内部結合と同値の相関サブクエリ
- 外部結合──何の「外部」なのか
- 外部結合の動作
- 外部結合と内部結合の違い
- 自己結合──自己とは誰のことか
- 自己結合の動作
- 自己結合の考え方
6.2 結合のアルゴリズムとパフォーマンス
- Nested Loops
- Nested Loopsの動作
- 駆動表の重要性
- Nested Loopsの落とし穴
- Hash
- Hashの動作
- Hashの特徴
- Hashが有効なケース
- Sort Merge
- Sort Mergeの動作
- Sort Mergeの特徴
- Sort Mergeが有効なケース
- 意図せぬクロス結合
- Nested Loopsが選択される場合
- クロス結合が選択される場合
- 意図せぬクロス結合を回避するには
6.3 結合が遅いなと感じたら
- ケース別の最適な結合アルゴリズム
- そもそも実行計画の制御は可能なのか?
- DBMSごとの実行計画制御の状況
- 実行計画をユーザが制御することによるリスク
- 揺れるよ揺れる,実行計画は揺れるよ
第6章のまとめ
演習問題6
第7章 サブクエリ──困難は分割するべきか
7.1 サブクエリが引き起こす弊害
- サブクエリの問題点
- サブクエリの計算コストが上乗せされる
- データのI/Oコストがかかる
- 最適化を受けられない
- サブクエリ・パラノイア
- サブクエリを使った場合
- 相関サブクエリは解にならない
- ウィンドウ関数で結合をなくせ!
- 長期的な視野でのリスクマネジメント
- アルゴリズムの変動リスク
- 環境起因の遅延リスク
- サブクエリ・パラノイア──応用版
- サブクエリ・パラノイア再び
- 行間比較でも結合は必要ない
- 困難は分割するな
7.2 サブクエリの積極的意味
- 結合と集約の順序
- 2つの解
- 結合の対象行数
第7章のまとめ
演習問題7
第8章 SQLにおける順序──甦る手続き型
8.1 行に対するナンバリング
- 主キーが1列の場合
- ウィンドウ関数を利用する
- 相関サブクエリを利用する
- 主キーが複数列から構成される場合
- ウィンドウ関数を利用する
- 相関サブクエリを利用する
- グループごとに連番を振る場合
- ウィンドウ関数を利用する
- 相関サブクエリを利用する
- ナンバリングによる更新
- ウィンドウ関数を利用する
- 相関サブクエリを利用する
8.2 行に対するナンバリングの応用
- 中央値を求める
- 集合指向的な解
- 手続き型の解(1)──世界の中心を目指せ
- 手続き型の解(2)──2マイナス1は1
- ナンバリングによりテーブルを分割する
- 断絶区間を求める
- 集合指向的な解──集合の境界線
- 手続き型の解──「1行あと」との比較
- テーブルに存在するシーケンスを求める
- 集合指向的な解──再び,集合の境界線
- 手続き型の解──再び,「1行あと」との比較
8.3 シーケンスオブジェクト・IDENTITY列・採番テーブル
- シーケンスオブジェクト
- シーケンスオブジェクトの問題点
- シーケンスオブジェクトそのものに起因する性能問題
- シーケンスオブジェクトそのものに起因する性能問題への対策
- 連番をキーに使うことに起因する性能問題
- 連番をキーに使うことに起因する性能問題への対策
- IDENTITY列
- 採番テーブル
第8章のまとめ
演習問題8
第9章 更新とデータモデル──盲目のスーパーソルジャー
9.1 更新は効率的に
- NULLの埋め立てを行う
- 逆にNULLを作成する
9.2 行から列への更新
- 1列ずつ更新する
- 行式で複数列更新する
- NOT NULL制約がついている場合
- UPDATE文を利用する
- MERGE文を利用する
9.3 列から行への更新
9.4 同じテーブルの異なる行からの更新
- 相関サブクエリを利用する
- ウィンドウ関数を利用する
- INSERTとUPDATEはどちらが良いのか
9.5 更新のもたらすトレードオフ
- SQLで解く方法
- SQLに頼らずに解く方法
9.6 モデル変更の注意点
- 更新コストが高まる
- 更新までのタイムラグが発生する
- モデル変更のコストが発生する
9.7 スーパーソルジャー病:類題
- 再び,SQLで解くなら
- 再び,モデル変更で解くなら
- 初級者よりも中級者がご用心
9.8 データモデルを制す者はシステムを制す
第9章のまとめ
演習問題9
第10章 インデックスを使いこなす──秀才の弱点
10.1 インデックスと言えばB-tree
- 万能型のB-tree
- その他のインデックス
10.2 インデックスを有効活用するには
- カーディナリティと選択率
- [Column]クラスタリングファクタ
- インデックスの利用が有効かを判断するには
10.3 インデックスによる性能向上が難しいケース
- 絞り込み条件が存在しない
- ほとんどレコードを絞り込めない
- 入力パラメータによって選択率が変動する(1)
- 入力パラメータによって選択率が変動する(2)
- インデックスが使えない検索条件
- 中間一致,後方一致のLIKE述語
- 索引列で演算を行っている
- IS NULL述語を使っている
- 否定形を用いている
10.4 インデックスが使用できない場合どう対処するか
- 外部設計による対処──深くて暗い川を渡れ
- UI設計による対処
- 外部設計による対処の注意点
- データマートによる対処
- データマートを採用するときの注意点
- データ鮮度
- データマートのサイズ
- データマートの数
- バッチウィンドウ
- インデックスオンリースキャンによる対処
- [Column]インデックスオンリースキャンとカラム指向データベース
- インデックスオンリースキャンを採用するときの注意点
- DBMSによっては使えないこともある
- 1つのインデックスに含められる列数には限度がある
- 更新のオーバーヘッドを増やす
- 定期的なインデックスのリビルドが必要
- SQL文に新たな列が追加されたら使えない