SQLを学びたいエンジニア向けのよい本
ただ多くの内容は著者ページ
http://www.geocities.jp/mickindex/database/idx_database.html
にあります
以下論点を
@コーディング規約大事
SELECT col_1, col_2, col_3, COUNT(*)
FROM tbl_A
WHERE col_1 = 'a'
AND col_2 = ( SELECT MAX(col_2)
FROM tbl_B
WHERE col_3 = 100 )
GROUP BY col_1, col_2, col3
のように先頭よりも末尾を揃えるほうがよいのでは
*(ワイルドカード)使わない
@パフォーマンスチューニング
・サブクエリを引数に取る場合INよりもEXISTSを
IN (1, 2, 3) のように値のリストではあまり気にする必要なし
INとEXISTSはたいていまったく斉しい結果を返しEXISTSが速く動作する
Class_A
id name
1 田中
2 鈴木
3 伊集院
Class_B
1 田中
2 鈴木
4 西園寺
Class_AからClass_Bにも存在する人を選択
以下は結果は同じでEXISTSのほうが早い
SELECT *
FROM Class_A
WHERE id IN (SELECT id
FROM Class_B);
SELECT *
FROM Class_A A
WHERE EXISTS
(SELECT *
FROM Class_B B
WHERE A.id = B.id);
理由
- 結合キー(id)にインデックスが張られていれば、Clsss_Bの実表は見に行かず、インデックスを参照するのみで済む
- EXISTSは一行でも条件に合致する行を見つけたらそこで検索を撃ち切るので、INのように全表検索の必要がない。NO EXISTSも同様
・以下はソートが発生する
GROUP BY
ORDER BY
SUM,COUNT,AVG,MAX,MIN
DISTINCT
UNION,INTERSECT,EXCEPT
例えば
SELECT * FROM Class_A
UNION
SELECT * FROM Class_B;
は必ず重複排除のためのソートを行う
重複を気にしないでよいor重複が発生しない場合は
SELECT * FROM Class_A
UNION ALL
SELECT * FROM Class_B;
とするとソートが発生しない
ソートしないためにDISTINCTをEXISTSで代用できる
item_no item
10 FD
20 CD-R
30 MO
40 DVD
sale_date item_no quantity
10-01 10 4
10-01 20 10
10-01 30
10-03
10-0
10-04
10-04
売上のあった商品を探す場合、INを使うと可読性はあっても重いので
SELECT DISTINCT I.item_no
FROM Items I INNER JOIN SalesHistory SH
ON I.item_no = SH.item_no;
よりも
SELECT item_no
FROM Items I
WHERE EXISTS
(SELECT *
FROM SalesHistory SH
WHERE I.item_no = SH.item_no);
が正解
MAXやMINを使う場合もソートが発生するのでインデックスがはられている列でできないか考える
WHEREで書ける条件はHAVINGには書かない
SELECT sale_date, SUM(quantity)
FROM SalesHistory
GROUP BY sale_date
HAVING sale_date = '~~';
よりも
SELECT sale_date, SUM(quantity)
FROM SalesHistory
WHERE sale_date = '~~'
GROUP BY sale_date
のほうが結果同じで高速に動作する
理由は
GROUP BYはソートが発生するので事前に絞り込んでソート負荷を減らしてあげる
WHEREの条件でインデックスが利用できること、HAVINGではインデックスは使えない
・インデックスが本当に使われているか?
SELECT *
FROM SomeTable
WHERE col_1 * 1.1 > 100;
はインデックスが使えない
WHERE col_1 > 100 / 1.1
ならインデックスが使える。
WHERE SUBSTR(col_1, 1, 1) = 'a';も使えない
インデックスを利用する時は条件式の左辺は裸に
インデックスにはNULLがないので WHERE col_l IS NULL; はダメ
<> != NOT IN のような否定形もインデックスを利用できない
ORを使うとインデックスを利用できないか、使えてもANDより低速
col1,col2,col3の順に複合インデックスがはられているとして
SELECT * FROM SomeTable WHERE col1 = 10 AND col2 = 100 AND col3 = 500;
SELECT * FROM SomeTable WHERE col1 = 10 AND col2 = 100;
はOK
SELECT * FROM SomeTable WHERE col1 = 10 AND col3 = 500;
SELECT * FROM SomeTable WHERE col2 = 100 AND col3 = 500;
SELECT * FROM SomeTable WHERE col2 = 100 AND col1 = 10;
はNG
SELECT * FROM SomeTable WHERE col1 LIKE 'a%';
はOK
SELECT * FROM SomeTable WHERE col1 LIKE '%a%';
SELECT * FROM SomeTable WHERE col1 LIKE '%a';
はNG
char型定義に対して
SELECT * FROM SomeTable WHERE col1 = 10;
はNG
SELECT * FROM SomeTable WHERE col1 = '10';
SELECT * FROM SomeTable WHERE col1 = CAST(10, AS CHAR(2));
はOK
あとがきにあるなぜ著者がDBの道に進んだかという話がおもしろい
最初DBの世界は地味でおもしろみを感じられなかった
そんなときに読んだ
rootから/へのメッセージで目を覚ました
http://cruel.org/other/ditodias.html より引用
なんでもないように見える世界のいたるところに、本質へ通じる道がある
本書を一読するだけで、あなたはこれまでの己の不徳を悟ることでしょう
おもしろいことが、「なんか」「どこか」にあって、それがいつか空からふってきてくれるのではないかという己の怠惰な発想を、あなたは深く恥じ入ることでしょう。
どこにでもあるものの中に著者は他の人には見えていない面白さを見て取ります。
それは時には仕事がらみで必要となる技能の修得がきっかけだったり、出張や通勤のついでだったり。
でも、ちっとも特別なものじゃない。
そう、「おもしろいこと」はいたるところにあったのです。
「つまんない」は世の中でも一日でもなく、目の前のものにおもしろさを見いだせない、自分の怠慢な目や耳や鼻や手足や頭だったのです
この言葉に感じ入りDBをはじめたとのこと。
自分以外の誰も自分の人生を楽しくなんかしてくれないよねー。
単純だけどいい文章。
★★★★