tom__bo’s Blog

MySQL!! MySQL!! @tom__bo

「SQL実践入門」読んだ

今年(2015)の5/15に初版が発売されたSQL実践入門(ミック著)を読んだ。

f:id:tom__bo:20150625161900p:plain

 

以前書いた ↓

tombo2.hatenablog.com

に引き続き、DB本を読んだエントリーです。

 

 「SQL実践入門」はDBMSの基本的なアーキテクチャの説明から始まり、SQLのパフォーマンスを向上するために重要な「クエリ評価エンジン」と「実行計画」にフォーカスを当てて、割りと大きめのデータ(メモリに乗る乗らないを意識するくらいの量のデータ)を扱うSQLをどう書くと良いのかを内部構造と共に説明してくれています。

 特に実行計画のサンプルが毎回と言っていいほど明示されているので、何が遅くなる原因で、どうして解決できるのかがわかりやすいと思います。クエリの書き方に関するノウハウは、扱っているテーブルの状況に依存していて、一概にこうするべき!と言えないなーと思っています。よって、ボトルネックを把握した上で、機能面や更新処理とのトレードオフを検討する必要がある場合が多いので、実行計画から解決の1パターンを示してくれているのはとても参考になりました。

 

上に挙げた、「データベース技術[実践]入門」がMySQLを例にして、主に大規模なWebサーバに紐付いたDBサーバとして "データベース技術" の説明をしているのに対して、こちらはどちらかと言うとそれらWebサーバのログ等を集計する分析用DBを想定した本になっています。

なので、DBのサンプルや実行計画は全てOracle DBとPostgreSQLで説明されていて、MySQLの例は出てくるものの「JOINの仕方にNested Loops系しかないよね。」といった登場の仕方だったりします。

とはいえ以下にメモリ上で、処理を完結するか、無駄なロジックを省くかといった基本は同じなので、RDBの勉強には最高でした。

 

 

自分自身のメモとしての意味が大きいですが、各章の概要と気になった点を書いてみます。

 

1章:DBMSアーキテクチャ 

 DBMSアーキテクチャについて

 バッファ、メモリ、HDDの概要とそれらのトレードオフについて

 DBMSの実行計画がどう決定されるのか

f:id:tom__bo:20150625225615j:plain

( ↑  SQL実践入門p.3より)

 

2章:SQLの基礎

 SELECT文を中心にWHERE, GROUPBY, HAVING句等の説明

 INSERT, DERETE, UPDATEの説明

 

3章:SQLにおける条件分岐

  UNIONの実行計画とCASE式での条件分岐

 

4章:集約とカット

  PARTITION BY句の利用

 

5章:ループ

  ループ処理による弊害とその対策

 SQLではどうやってループ処理をするか

 

6章:結合

 クロス結合、内部結合、外部結合の違い

 結合のアルゴリズム(Nested Loops, Hash, Sort Merge) 

 

7章:サブクエリ

 サブクエリの問題点

 ウィンドウ関数で結合をなくす

 集約と結合の順序

 

8章:SQLにおける順序

 行に対するナンバリング 

  シーケンスオブジェクトについて

 

9章:更新とデータモデル

 更新のもたらすトレードオフ

 モデル変更の注意点 

 

10章:インデックスを使いこなす

  カーディナリティ、選択率、クラスタリングファクタについて

 インデックスの活用

 インデックスが活用できないケースとその対策

 

 

かなり粗いですが概要はこんな感じです。どの章も「初心者はこうしてしまいがちだけど、実行計画がこうなるからこの書き方のほうがいい」といった流れで説明されているので、非常にわかりやすく、状況が変わっても対応できそうな基本的なロジックが理解出来ました。

 

3,4章のCASE式での条件分岐、集約とカットはまさに最近書くようになったクエリで、集計のストアドにはよく出てくるので、「こう書くのか〜」と思っていましたが、実行効率の点でも具体的な裏付けを説明してもらえた!という感じでした。

 

と、感想を言っていってもしょうがないので、気になった点まとめ

 

・カタログマネージャに含まれている統計情報(p22)

 実装によっても異なるらしいが、製品ごとの違い、オプティマイザの判断基準も見たい。。。

 本の中では以下が上げられていた。

 ・各テーブルのレコード数

 ・各テーブルの列数と列のサイズ

 ・列値のカーディナリティ(値の個数)

 ・列値のヒストグラム(どの値がいくつあるかの分布)

 ・列内にあるNULLの数

 ・インデックス情報

 

・window関数(RANGEとかROWS) (p67)

 PARTITION BY, ORDER BYくらいしか知らなかった。というかSUM, AVGとかもそうだった。

 参考:SQLクリニック(9):SQL分析関数をさらに深く追求してみよう (1/2) - @IT

 

SQL実行のオーバーヘッド(p131)

 ISUCONで使うかな?

 <前処理>

 ・SQL分のネットワーク転送

 ・データベースへの接続

 ・SQL分のパース

 ・SQL分の実行計画生成及び評価

 <後処理>

 ・結果セットのネットワーク転送

 

・"MySQLにはNested Loopsしかない" (p195)

 Nested Loopsの他に、これの改良版であるBlock Nested Loop。

 インデックスアクセスを利用する Batched Key Accessがあるよう。

 説明は省略。

 参考:

 MySQL :: MySQL 5.6 リファレンスマニュアル :: 8.2.1.10 Nested Loop 結合アルゴリズム

 MySQL :: MySQL 5.6 リファレンスマニュアル :: 8.2.1.14 Block Nested Loop 結合と Batched Key Access 結合

 

・カーディナリティ, 選択率, クラスタリングファクタ(p301)

 重要単語!テスト出るよ(何の!?)

 カーディナリティ:カラムの値のバラつき具合。1つの値で一意になる時が一番高い。

 選択率:特定の列の値を指定した時に行をテーブル全体の募集号からどの程度絞り込めるかを示す。

 クラスタリングファクタ:物理領域で値がどれくらい同じ箇所にあるか。同じ値が固まっている(=クラスタリングファクタが低い)ほどインデックスでのアクセスに有利

 

  インデックスが有効になのはカーディなり体が高く、選択率が低いこと。

つまり、列内の値がばらついていて、ある条件で少ない行に絞り込める状態であること。

最近のDBMSでは、選択率が5~10%前後が目安。

 

 

 

 

ー まとめ ー

 

分析系の業務には必携になりそうな本を見つけられて幸せ。

実行計画の調整、実行順序をもっと意識してSQL書こうと思います。

次回は「データベース実践入門」かな。

 

⊂゚U┬───┬~

終わり