SQLのEXPLAINってなに?|データベースが考えていることを見てみましょう

こんにちは、さるまりんです。

SQLを書いていると、

「このSQL、重いですね〜」

と言われたり、

「インデックスを貼っていますか?」

なんて言われることがあります。

考えないといけないことではあるのですが、

  • データベースがどうやってデータを探しているのか
  • なぜ速いSQLと遅いSQLがあるのか

を意識するのは、少し後になってからなんですよね。

そんな時に役立つのが EXPLAIN です。

今回は、EXPLAINを使ってデータベースがどんなことを考えているのかを、ちょっと覗いてみたいと思います。

EXPLAINとは?

一言で言うと、

SQLをどのように実行しようとしているかを見るための機能

です。

例えば次のSQLがあります。

SELECT *
FROM users
WHERE id = 1;

「idが1のユーザーを取得するSQL」です。

もちろんそれで間違いないです。

でも、データベースはその前に、

どうやって探そうかな?

ということを考えています。

EXPLAINは、その考えている内容を見せてくれる機能なんです。

データベースは作戦を立てている

例えば本棚を想像してみてください。

本が10冊しかなければ、最初から順番に見ていってもすぐに見つかります。

でも100万冊あったらどうでしょう。

順番に探していたら大変です。ものすごい時間がかかりますよね。

そこで、

  • ジャンルごとに分ける
  • 索引を使う
  • 並び順を工夫する

といった方法を考えます。

データベースも同じです。

データが少ない時と多い時では、効率の良い探し方が変わってきます。

そしてデータベースは、どの方法が良さそうかを考えてからSQLを実行してくれます。

実際にEXPLAINを使ってみる

今回はPostgreSQLを例にします。

ただし、考え方そのものは多くのデータベースで共通です。

まずはテーブルを作ります。

CREATE TABLE users (
    id INTEGER PRIMARY KEY,
    name VARCHAR(100)
);

データを入れてみます。

INSERT INTO users
SELECT
    generate_series,
    'user_' || generate_series
FROM generate_series(1, 10000);

そしてEXPLAINを実行します。

EXPLAIN
SELECT *
FROM users
WHERE id = 5000;

結果は環境によって多少異なりますが、例えば次のような内容が表示されます。

Index Scan using users_pkey on users

ここでは細かい意味までは入りません。

まずは、

Index Scan が使われている

ということだけ見てみましょう。

これは、

インデックスを使って探そうとしている

という意味です。

データベースが効率の良い探し方を選んでくれていることが分かります。

インデックスがなかったら?

今度はインデックスのないテーブルを作ってみます。

CREATE TABLE users_no_index (
    id INTEGER,
    name VARCHAR(100)
);

同じデータを入れます。

INSERT INTO users_no_index
SELECT
    generate_series,
    'user_' || generate_series
FROM generate_series(1, 10000);

そして同じように実行してみます。

EXPLAIN
SELECT *
FROM users_no_index
WHERE id = 5000;

すると、

Seq Scan on users_no_index

のような結果になることがあります。

SeqはSequentialの略です。

順番に読むという意味ですね。

つまり、

とりあえず最初から見ていこう

という作戦を選んでいることになります。

データが少なければ問題ありませんが、データが増えてくると時間がかかる可能性があります。

順番に探していくため、探す範囲が広くなるほど時間もかかりやすくなります。

EXPLAINを見ると何が分かるの?

EXPLAINを見ることで、例えば次のようなことが分かります。

  • インデックスが使われているか
  • テーブルを順番に読んでいるか
  • JOINをどのような順番で実行しているか
  • データベースがどんな作戦を選んだか

実際の開発では、

「SQLが遅い」

という話になった時にEXPLAINを見ることがよくあります。

私がEXPLAINを見る時

私の場合、SQLの結果がおかしい時よりも、SQLの動きが気になる時に使うことが多いです。

例えば、

  • JOINを増やした時
  • インデックスを追加した時
  • データ量が増えてきた時

などです。

SQLを書く時は結果ばかり見てしまいがちですが、EXPLAINを見ると、データベースがどんな考え方で動いているのかが少し見えてきます。

まとめ

EXPLAINは、SQLを実行する前にデータベースが考えている作戦を見るための機能です。

最初は表示内容が難しく見えるかもしれません。

でも、

  • データベースは作戦を立てている
  • EXPLAINはその作戦を見るためのもの

ということだけ覚えておくだけでも、データベースの扱いに強くなると思います。

SQLを書くことに慣れてきたら、次はデータベースがどう考えているのかも考えてみると面白いかもしれません。

私自身も、

「SQLが遅くなってから見る」

ではなく、

「気になったら見てみる」

くらいの気持ちでEXPLAINと付き合っていきたいなと思っています。

読んでくださってありがとうございました。

それでは、また!