Skip to content

Instantly share code, notes, and snippets.

@kano-e
Last active December 28, 2021 23:19
Show Gist options
  • Save kano-e/8d75be08037809fd280d to your computer and use it in GitHub Desktop.
Save kano-e/8d75be08037809fd280d to your computer and use it in GitHub Desktop.
SQL と仲良くなる話

SQL可愛い

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


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 健気で可愛い。
NULL で困っちゃうところも可愛い。

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

SQL ほんと可愛い。


明日の担当はa-knowさんです!

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