[Rails] RubyistのためのPostgreSQL EXPLAINガイド(翻訳)

こんにちは、hachi8833です。今回は「A Rubyist’s Guide to Postgresql’s Explain」の翻訳記事をお届けいたします。 EXPLAINはSQLの構文なので、本記事では元記事のタイトルとコードを除き大文字で表記します。 概要 原著者の許諾を得て翻訳・公開いたします。 元記事: A Rubyist’s Guide to Postgresql’s Explain 原著者: Starr Horne 元サイト: RubyLetter — 週一ペースで多くの良記事が公開されています。おすすめです。 なお、翻訳では元記事にないコードのハイライトをスクリーンショットとして追加しています。 RubyistのためのPostgreSQL EXPLAINガイド PostgreSQLにはEXPLAINと呼ばれるささやかな機能があります。ささやかですが、「このところなぜかデータベースクエリが遅い」という問題を解決するうえで最強の武器にもなります。 EXPLAINのしくみは単純です。PostgreSQLにクエリをどのように実行するかを問い合わせると、PostgreSQLがクエリプランを表示してくれます。そのクエリを実際にEXPLAINで実行して、実際のパフォーマンスと比較することもできます。 なかなか使いやすそうだけど? EXPLAINという機能があることは何となくご存じのRailsエンジニアもいると思います。実はRails 3.2というかなり早い時期から、クエリ実行時間が500msを超えたときに自動的にEXPLAINが実行されるようになっているのです。 問題があるとすれば、EXPLAINの出力が少々込み入ってることぐらいでしょう。出力例として、当サイトのRails開発ブログから出力結果を引っ張ってきました。 % User.where(:id => 1).joins(:posts).explain EXPLAIN for: SELECT “users”.* FROM “users” INNER JOIN “posts” ON “posts”.”user_id” = “users”.”id” WHERE “users”.”id” = 1 QUERY PLAN —————————————————————————— Nested Loop Left Join (cost=0.00..37.24 rows=8 width=0) Join Filter: (posts.user_id = users.id) -> Index Scan using users_pkey on users (cost=0.00..8.27 rows=1 width=4) Index Cond: (id = 1) -> Seq Scan on posts (cost=0.00..28.88 rows=8 width=4) Filter: (posts.user_id = 1) (6 rows) さて、この出力から一体何を読み取ればよいのでしょうか? 本記事ではこうした出力結果を解釈する方法をご紹介いたします。特に、クエリがRubyを用いたWeb開発にいかに大きな影響を与えるかという点に重点を置きます。 EXPLAIN出力の構文 既にRailsをお使いであれば、以下のようにActive Recordのクエリに.explainを追加するだけで簡単にEXPLAINを実行できます。 > User.where(id: 1).explain User Load (10.0ms) SELECT “users”.* FROM “users” WHERE “users”.”id” = $1 [[“id”, 1]] => EXPLAIN for: SELECT “users”.* FROM “users” WHERE “users”.”id” = $1 [[“id”, 1]] QUERY PLAN ————————————————————————– Index Scan using users_pkey on users (cost=0.29..8.30 rows=1 width=812) Index Cond: (id = 1) (2 rows) #explainメソッドはお手軽ですが、PostgreSQLで直接EXPLAINを実行する場合に使える高度なオプションには残念ながらアクセスできません。 PostgreSQLでEXPLAINを直接実行したい場合は、psql -d データベース名でpostgres clientを開き、以下のように実行するだけで済みます。 explain select * from users where id=1; QUERY PLAN ————————————————————————– Index Scan using users_pkey on users (cost=0.29..8.30 rows=1 width=812) Index Cond: (id = 1) (2 … Continue reading [Rails] RubyistのためのPostgreSQL EXPLAINガイド(翻訳)