「データベース実践入門」読了
理論から学ぶデータベース実践入門 ~リレーショナルモデルによる効率的なSQL (WEB+DB PRESS plus)
- 作者: 奥野幹也
- 出版社/メーカー: 技術評論社
- 発売日: 2015/03/10
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (15件) を見る
集合論に関する最初の方の章を読み進めるのは少し我慢が必要だが、それほど長くないし、分かり易いので問題ではなかった。最後の14.3章だけを最初に読んでみてもいいかもしれない。それだけで知見が手に入るし、読み始める良いきっかけになると思う。
テーブルは多重集合であるため、SQLをリレーショナルモデルに沿って使うためには、テーブルを集合と同じように使う必要がある。つまり、少なくとも何らかの一意性制約は必要。
集合には順序がない。だから集合論から見ると、SQLのROWNUMやORDER BY 1(この1はSELECT句の列指定の順に付けた番号。1番目の列ということ)は使うべきでない。
リレーションは値、テーブルは値と変数の両方を兼ね備えている。だからテーブルは更新できる。
テーブルをリレーションの性質に近づけるように設計するべきである。
インデックスがないテーブルと、インデックスが1つあるテーブルでは、更新処理のオーバーヘッドは、後者が倍になる。インデックスを増やすと更新処理のオーバーヘッドは(線形に)上がっていく。
列挙型(ENUM)をテーブルに定義して使うマスタテーブルという手法。列挙型をデータ型としてサポートするDBもあり、サイズがコンパクト。
CHECK制約で列の値に対する任意の・複数カラムの条件が付けられる。
NULLを示す特別な値を確保してNOT NULL制約のデフォルト値とすることは、NULLを許容する場合と同じか、場合によってはより悪くなる。
COALESCE関数はダイナミックデフォルトと呼ばれるもので、最初に出現するNULLでない値を返す。集計関数やスカラサブクエリなど、どうしてもNULLになる可能性があるものに利用する。IFNULL関数はSQL標準ではない。
集約関数の中でCOUNTだけが空集合に対する結果がNULLでなく0になる。
簡単に、WHERE句は集計前の条件指定、HAVING句は集計後の条件指定、と覚える。
HAVING句の条件はGROUP BY句で指定したカラムか集計関数の結果だけを扱える。GROUP BY句の結果が0の場合は出力されないが、これは相関サブクエリで解決できる。
UNIONで同じテーブルの和集合を作る。
テーブルは小さく作る、の利点は、サイズを小さく抑えることにより、B+ツリーの検索が速くなること。より頻繁にアクセスするテーブルはより小さくする。
Twitter/FlockDB
FS上のディレクトリにハードリンクが作成できないのは、ツリー構造に閉路を作っていまうため。
B+ツリーについて、ノンリーフノードには子ノードの最小値が格納されている。また、子ノードへのポインタとなるページIDが格納されている。
全文検索は転置インデックスで実装される。転置インデックスとは、文を行に分けて、単語と出現する行を、テーブルの行として格納する。
InnoDBでは全てのテーブルがクラスタインデックスとして作成される。つまり主キーが定義されていないテーブルであっても、内部的にはキーを定義してインデックスツリーを構築する。
クラスタインデックスを用いている場合、セカンダリインデックスはリーフノードに主キーの値を持っている。つまり、セカンダリインデックスとクラスタインデックスの両方のツリーを辿る必要がある。
クラスタインデックスを用いない場合、セカンダリインデックスはリーフノードにデータへのポインタ(ページ番号やオフセット)を持っている。つまり、セカンダリインデックスを辿るだけでよい(あとはディスクシークのみ)。
カバリングインデックスとしてセカンダリインデックスに追加しておけば、クラスタインデックスにアクセスする必要なく、読み出すべき全てのカラムにアクセスできる。
関数インデックスは、(複数の)カラムに関数を適用した後の値に対してインデックスを作成することができる。
パーティションは一意性を保証できないので、主キーやユニークインデックスにはパーティションキーを含めることで保証できるが、そんな必要があるのならはじめからパーティションしない方がよい。
パーティションとは刈り込みのことであり、刈り込みが有効になるようにテーブルやアプリを設計すること。
マルチカラムインデックスには順序があるので、順序を入れ替えたマルチカラムインデックスは別物として有効。
JOINとマルチカラムインデックス、内部表からフェッチする時点でON句とWHERE句に指定したカラムを含むマルチカラムインデックスを用いることで、フェッチの際に大きな絞り込みが行われる。
OR条件ではマルチカラムインデックスは使えず、個々のインデックスが必要になる。インデックスマージにより和集合を取得する。
マルチカラムインデックスは、並び順・カーディナリティ・組み合わせの最適化、を考える。
キャッシュ目的でテーブルを非正規化する選択はあり得る。
マテリアライズドビューはビューにアクセスするたびにクエリを実行するのではなく、クエリの実行結果をキャッシュしておく。
(INNER)JOIN は等価条件を付けない場合に直積となる。
リファクタリングではカラムを追加するよりテーブルを追加するほうが良い。JOINを嫌ってはいけない。
SELECT * はカラムの順序がソートされていることを期待しているが、それは正しくない。これは使わないこと。
データが正しく保たれている状態とは、個々のトランザクションをシーケンシャルに実行したときと同じ結果になる状態のこと。
SELECT … FOR UPDATE で読み込み時に強制的にロックをかけて、一時的に分離レベルをシリアライザブルに変更する。WAITを指定することで他トランザクションがロックしている場合はコミット・ロールバックするまで待つこともできる。NOWAITを指定すると他トランザクションがロックしている場合は即座に処理を戻す。