目次
- はじめに──クラウドネイティブ時代にパフォーマンスチューニングはどのような意味を持つか
 - 動作環境
 - サンプルコードのダウンロード
 - 本書の構成
 - 目次
 
第1章:DBMSのアーキテクチャ──この世にただ飯はあるか
1.1 DBMSのアーキテクチャ概要
- クエリ評価エンジン
 - バッファマネージャ
 - ディスク容量マネージャ
 - トランザクションマネージャとロックマネージャ
 - リカバリマネージャ
 
1.2 DBMSとバッファ
- この世にただ飯はあるか
 - DBMSと記憶装置の関係
- HDD
 - SSD
 - メモリ
 - バッファの活用による速度向上
 
 - メモリ上の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]インデックスオンリースキャン
 
 - ループ回数が不定の場合
- 隣接リストモデルと再帰クエリ
 - OracleのCONNECT BY句
 
 
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章のまとめ
- [Column]性能試験はどの環境で行うべきか
 
演習問題6
第7章:サブクエリ──困難は分割するべきか
7.1 サブクエリが引き起こす弊害
- サブクエリの問題点
- サブクエリの計算コストが上乗せされる
 - データのI/Oコストがかかる
 - 最適化を受けられない
 
 - サブクエリ・パラノイア
- サブクエリを使った場合
 - 相関サブクエリは解にならない
 - ウィンドウ関数で結合をなくせ!
 
 - 長期的な視野でのリスクマネジメント
- アルゴリズムの変動リスク
 - 環境起因の遅延リスク
 
 - サブクエリ・パラノイア──応用版
- サブクエリ・パラノイア再び
 - 行間比較でも結合は必要ない
 
 - 困難は分割するな
 
7.2 サブクエリの積極的意味
- 結合と集約の順序
- 2つの解
 - 結合の対象行数
 
 
第7章のまとめ
演習問題7
第8章:SQLにおける順序──甦る手続き型
8.1 行に対するナンバリング
- 主キーが1列の場合
- ウィンドウ関数を利用する
 - 昔は相関サブクエリを利用していた
 
 - 主キーが複数列から構成される場合
- ウィンドウ関数を利用する
 
 - グループごとに連番を振る場合
- ウィンドウ関数を利用する
 
 - ナンバリングによる更新
- ウィンドウ関数を利用する
 
 
8.2 行に対するナンバリングの応用
- 中央値を求める
- 集合指向的な解
 - 手続き型の解❶──世界の中心を目指せ
 - 手続き型の解❷──2マイナス1は1
 
 - ナンバリングによりテーブルを分割する
- 断絶区間を求める
 - 集合指向的な解──集合の境界線
 - 手続き型の解──「1行あと」との比較
 
 - テーブルに存在するシーケンスを求める
- 集合指向的な解──再び,集合の境界線
 - 手続き型の解──再び,「1行あと」との比較
 
 
8.3 シーケンスオブジェクト・IDENTITY列・採番テーブル
- シーケンスオブジェクト
- シーケンスオブジェクトの問題点
 - シーケンスオブジェクトそのものに起因する性能問題
 - シーケンスオブジェクトそのものに起因する性能問題への対策
 - 連番をキーに使うことに起因する性能問題
 - NewSQLにおけるホットスポットの発生
 - 連番をキーに使うことに起因する性能問題への対策
 
 - 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 インデックスによる性能向上が難しいケース
- 絞り込み条件が存在しない
 - ほとんどレコードを絞り込めない
- 入力パラメータによって選択率が変動する❶
 - 入力パラメータによって選択率が変動する❷
 
 - インデックスが使えない検索条件
- 中間一致,後方一致のLIKE述語
 - 索引列で演算を行っている
 - IS NULL述語を使っている
 - 否定形を用いている
 
 
10.4 インデックスが使用できない場合どう対処するか
- 外部設計による対処──深くて暗い川を渡れ
- UI設計による対処
 
 - 外部設計による対処の注意点
 - データマートによる対処
 - データマートを採用するときの注意点
- データ鮮度
 - データマートのサイズ
 - データマートの数
 - バッチウィンドウ
 
 - インデックスオンリースキャンによる対処
- [Column]インデックスオンリースキャンとカラム指向データベース
 
 - インデックスオンリースキャンを採用するときの注意点
- DBMSによっては使えないこともある
 - 1つのインデックスに含められる列数には限度がある
 - 更新のオーバーヘッドを増やす
 - 定期的なインデックスのリビルドが必要
 - SQL文に新たな列が追加されたら使えない
 
 
第10章のまとめ
演習問題10
- Appendix A:PostgreSQLのインストールと接続設定
 - Appendix B:MySQLのインストールと接続設定
 - Appendix C:演習問題の解答
 
- 索引
 - 著者プロフィール