Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
SQL と仲良くなる話

フィードフォースエンジニア Advent Calendar 2015 の2日目の記事です。
1日目の記事はCTOすーさんfeedforceアドベントカレンダー2015が始まります! でした。


SQL と仲良くなる話

SQL 大好き

普段から「SQL大好き」とか「SQL可愛い」とか言っているけど、ほんと SQL 可愛い。

最近、自分が SQL を勉強しはじめたくらいの頃のメモを見返すことがあったのだけれども、だいぶ初々しい感じだった。
まだ SQL のことをよく知らなくて「もっと仲良くなりたいのに、なかなか近づけない……!」というすれ違う少女漫画のような距離感で SQL と付き合っていたなあ。と遠い目になった。

今は SQL 可愛い (ほんと可愛い) と思ってるけど、あの頃よりは、少し……ほんの少しかもしれないし幻想かもしれないけど、仲良くなれたのかなあ。
なれてると良いなあ。

仲良くなるために何をやったかっていうのは、具体的には色々やった……と思うので、なかなかぱっとは言えないけど。
相手を知ろうとすることが、仲良くなる基本かもしれないなあ、とか思った。

SQL のことを知るためには、結局 RDB のこととか、設計のこととか、色々なことを知る必要があって。
そんな色々なことの積み重なりで SQL の仕事のやり方がわかるようになって。
そこからどう書いたら良いかもわかるようになってきた、という感じかも。

そんな、比喩過多で雑な SQL の話をします。

SQL は健気

SQL 可愛いって、もう何度も言ってるけど SQL が可愛い理由は、なんといってもその健気さ。

例えば ORDER BY って割とパフォーマンスに影響が出やすいのだけれども。
ORDER BY って、指定されたカラムの比較を行う必要があるから。

ORDER BY 指定せずに LIMIT 10 する時と比べるとわかると思うけれども。
ORDER BY なしの時には、単に適当に LIMIT で指定された件数を SELECT で持ってきたら良いってだけ。
今回の場合は 10 件見つかれば、そこで終わり。
10 件以上のレコードを見る必要はない。

だけど ORDER BY した上で LIMIT 10 すると、最初の 10 件を見つけるために全レコードの ORDER BY で指定されたカラムを見て比較しないといけない。
比較して、並べ替えて、ようやく最初の 10 件が見つかる。

例えばこの時、テーブルにレコードが 10_000 件あったら?
100_000 件だったら? それ以上だったら?

よく考えたら全くその通りの話なんだけれども、初心者の頃の色々わかってなかった自分はこういうところまで頭がまわってなかった。

ちなみに ORDER BY のパフォーマンス対策としてはインデックスが一般的だけれども。
それもデータの件数や偏り具合によっては効果が薄かったりする。
並べ替えの対象を減らせるならそれは効果がある、かも?

SQL の仕事量を考える

SQL のパフォーマンスチューニングについて調べると、
JOIN は重い」
「サブクエリは使うな」
ってよく聞く。
今はどうかな。自分が初心者の頃は、そういう記事をいっぱい見た。

それも、中で何が起こっているかがわかると、やみくもに「使っちゃ駄目」って思わなくても良くなる。

そもそも、なんで JOIN やサブクエリが重くなるかっていったら ORDER BY の時と同じ。
SQL に書かれた通り、その通りに、全部を、処理対象にするから。

例えば、FROM に指定したテーブル A のレコードが 10_000 件、LEFT OUTER JOIN に指定したテーブル B のレコードが 1_000 件あった場合を考える。
テーブル A のレコード件数分、テーブル B の対象レコードを探す処理が必要になる。 これは、最悪の場合 10_000_000 (= 10_000 * 1_000) レコード分の処理になる。

もっと件数が多かったら?
JOIN は掛け合わせなので、元になる情報が大きければ大きいほど、その結果は膨れ上がる。
ON に指定するカラムにインデックスはってあれば多少はマシになるけど、掛け合わせた結果の多さはどうしようもない。

で。
JOIN が遅い時、サブクエリを使うと速いことがある。
その頃の自分は「サブクエリは使わない方が良い」というのを鵜呑みにしていたので、その結果にびっくりしたことがある。

「サブクエリの遅さ」は何か、というと、サブクエリの SELECT 結果が仮のテーブルとして作られてしまうこと。
その仮のテーブルはメモリ上に、メモリが足りなければ実ファイルに、作られる。
当然、その分重くなる。
SELECT の結果が大量ならなおさら。

だけれども。
サブクエリの SELECT の結果が有限で、現実的な件数に収まるような場合には、JOIN の掛け合わせよりも、サブクエリが仮のテーブルを作る方が仕事量少ない! ってことになる。

よかれと思ってすれ違うこともある

インデックス使うと大抵はやくなるけど、たまにかえって仕事を増やす結果になることもあるって話。
(最近は RDB が賢くなってそういうこともあまりないのかな、どうなんだろう)

インデックスを使って絞り込んだり並べ替えたりした後に、結果を返すためにレコード全体を取得するのだけれども。
その時に必要な情報というのは基本、あちこちに、ばらばらに、点在してしまっている。

その散らばった情報を集めてまわるのも、仕事のひとつ。 なので、仕事が増えた分だけ、結局時間がかかることになる。
みたいなこともあったりする。

ケースバイケースというか、いつも、必ず、うまくいく方法はなくて、毎回 SQL と向き合わないといけないのかもしれないなあ。

SQL 可愛い

SQL 健気で可愛い。
NULL で困っちゃうところも可愛い。

うっかり色々仕事をさせると頑張りすぎちゃうので、ほどほどに。
仕事を押し付けすぎないようにすると、うまくお付き合いできそう。
って思ってる。

SQL ほんと可愛い。


さて、3日目の記事はFFエンジニアの可愛い担当 a-knowFF社のホワイトボードたちをご紹介します(੭ु ›ω‹ )੭ु⁾⁾です!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment