はじめに──クラウドネイティブ時代にパフォーマンスチューニングはどのような意味を持つか
動作環境
サンプルコードのダウンロード
本書の構成
目次
第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:演習問題の解答
索引
著者プロフィール