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日目の記事です。 昨日の記事は (公開前に書く) でした。

はじめに

  • SQL の勉強をはじめたばかりの頃の自分のメモを見返したら初々しかった
  • その頃はよくわかってなくて「SQL と仲良くなりたいのに仲良くなれない」と思っていた
  • 今は「SQL 可愛い」って思ってる
  • すごくかどうかはわからないけど、あの頃よりは仲良くなれたと思う
  • 仲良くなるためのポイントはチューニングかなあと思った
  • チューニングするためには、その SQL を実行すると何が起こるのかを知っている必要がある
  • 仲良くなる基本は相手を知ろうとすることかもしれない
  • explain の話とかはしない (予定)
  • イメージ先行でちょっと雑に話す

ORDER BY で起こること

  • ORDER BY 使うと全部並べ替えようとする
  • ORDER BY 使わずに SELECT するのは速いけど、実際の業務では現実的ではない
  • インデックス使うのが一般的
  • インデックスはソートされているようなものなので、インデックスがあれば ORDER BY はインデックスを元に行われる

LEFT JOIN で起こること

  • LEFT JOIN する時、大抵は ON で JOIN の結合条件を設定する
  • FROM に指定したテーブル A のレコードが 10_000 件、JOIN に指定したテーブル B のレコードが 1_000 件あった場合
    • テーブル A のレコードの件数分、テーブル B の対象レコードを探す処理が必要になる
    • これは、最悪の場合 10_000_000 レコード分の処理になる (10_000 * 1_000)
  • JOIN は掛け合わせなので、元になる情報が大きければ大きいほど、その結果が膨れ上がることになる
  • 一般的に JOIN が遅いって言われているのは、これのせい
  • ON に指定するカラムにインデックスはってあれば多少はマシになる
  • 掛け合わせる対象を絞り込むのが効果的
  • テーブル A の情報 100 件が必要だとわかっているなら、あらかじめ 100 件絞り込んでおけば良い
  • サブクエリを使うと効果的
  • SQL 勉強したての頃「サブクエリは遅い」と見かけたので、サブクエリ使ったら速くなってびっくりしたことがある
  • 「サブクエリの遅さ」は、サブクエリの SELECT 結果が仮のテーブルとして作られてしまうこと
  • サブクエリ内の SELECT 結果が有限で、現実的な件数に収まるのであれば、サブクエリ使った方がはやい

仕事が増えた分だけ実行結果が遅くなる

  • 当たり前のようだけれども、何もしないのが一番速い
  • ORDER BY は、対象テーブルのレコードの件数だけ仕事が増える
  • JOIN は、対象テーブル二つのレコード件数を掛け合わせた分だけ増える

インデックスを使っても遅くなるケース

  • インデックスを使って絞り込んだり並べ替えたりした後に、結果を返すためにレコード全体を取得する
  • その時に、必要な情報というのはあちこちに、ばらばらに、点在してしまうことになる
  • その散らばった情報を集めてまわるのも、仕事のひとつ
  • 仕事が増えた分だけ、結局時間がかかることになる

おわりに

  • SQL は「これだけお願い」と言ったらその通りに実行しようとしちゃう可愛いやつ
  • SQL に仕事を押し付けすぎないようにして、仲良くなろう
  • SQL に任せずに、アプリで吸収した方が効率良いことも多いよ

明日の記事は (公開前に書く)

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