そーくのつれづれぶろぐ

web系エンジニアの勉強したことなど

【PostgreSQL】やっぱり実行計画を読めるようになりたい!3つのおさらいポイント

はじめに

この記事は「ラクス Advent Calendar 2019」の11日目の投稿です。
昨日は@FlatMountainさんのJavaでArduinoを動かしてみた!でした。Arduino楽しそう...

いきなりですが、今年の3月に弊社技術ブログにて以下の記事を投稿しました。(id違いますが同一人物です)。まえがきを以下のように書いていました。

tech-blog.rakus.co.jp

...実行計画を読み解く記事を書こう!...と思いたったのですが、記事を書くにあたって ...(中略)...備忘も込めて当初予定していた記事を書く前に大量データの投入について述べたいと思います。

見逃してはいけない部分は "備忘も込めて当初予定していた記事を書く前に" ですね。

そうです、当初予定していた実行計画を読み解く記事を書く書く詐欺をして12月を迎えてしまったわけです。これは書かねばならぬと思いアドベントカレンダーの枠で投稿しようと決意しました。

私の経験ですが、入門記事や動画を見て「実行計画完全に理解した」みたいな気持ちで実務で実行計画を出してみた瞬間、己の無力さを噛み締め天を仰ぎました。 実務のSQLの実行計画を見ながら手探りでネットで検索しながら実行計画を見直し...を繰り返しようやくまあまあ読めるようになった、と今は思います。

この記事ではそんな私が振り返ってみて感じた実行計画を読むにあたって押さえるべきポイント3つを紹介したいと思います。

実行計画を読むポイント

  1. 実行計画のネストに注目する
  2. ノードがSQL文のどの句にあたるかを覚える&処理の内容を理解する
  3. 実行計画からSQLとリンクするキーワードを探す

実行計画を読む目的の多くは「パフォーマンス劣化を改善する」かと思います。なのでまずはパフォーマンス劣化している箇所を特定する必要があります。が、特定ができない...特定ができない原因はSQLと実行計画の対応付けができていないことではないでしょうか。この3つのポイントを押さえれば最終的に実行計画のどの行がSQLのどの句にあたるのかがわかる→パフォーマンス劣化を引き起こす箇所の特定ができるのではと考えています。

1. 実行計画のネストに注目する

入門記事ではだいたい書いてある気がしますが、あえてポイントとして挙げています。複雑な実行計画になればなるほどノードとSQLの対応付けが難しいです。30行くらいになるとひとつひとつ虱潰しに...となると心が折れそうになります。ですが、ネストの同じ階層を見ていくとだいたいサブクエリなどのひとかたまりの処理になっていますので、まずはネストを見ることでざっくりSQLのサブクエリや結合テーブルが実行計画のどのあたりに出現するのかを把握することができ、原因箇所の特定がしやすくなります。

2. ノードがSQL文のどの句にあたるかを覚える&処理の内容を理解する

これはかなり重要です。覚えておかないとそもそもどの処理をやっているのか全くわからないので英単語と一緒で最低限は知っておく必要があります。
ノードはかなりの種類があるのですが、SQLの処理からノードを対応付けて覚えると覚えることが少なく済むと思います。 実行計画をSQLに落とし込むことで初めてチューニングができるので、細かいノードの意味よりは先にSQLでいうとどこに当たるか?というところに目を向けるとよいでしょう。

SQLでやっている処理はたいてい「①結合して、②欲しい情報を探索して、③データを演算して、④ソートする」の4種類くらいで、次の表からわかるようにそれぞれ複数のノード(=処理方法)が存在しています。

処理 SQL 代表的なノード名
①結合処理 JOIN Nested Loop Join/Hash Join/Marge Join
②探索処理 WHERE/結合処理過程で内部的に実施など Index Scan/Seq Scan/Index Only Scan
③演算処理 GROUP BY/SUM/LIMITなど Aggregate/Hash Aggregate/Limit
④ソート処理 ORDER BY/結合処理過程で内部的に実施など Sort

ノードによっては別のノードを必ず呼び出すものもあるため、各ノードがどのような処理をしているのかを頭にいれておくことで、想定外のノードが出現する理由がわかるようになります。 SQLがどのように実行されているかを理解することで、パフォーマンス劣化の原因特定に1歩近づくでしょう。

3. 実行計画からSQLとリンクするキーワードを探す

WHERE句やON句などにでてくるカラム名やテーブル名は実行計画に書かれるため、ポイント1,2でアタリをつけたあと、詳細にSQLとの対応関係を把握するには、SQLにあるカラム名やテーブル名を探すことが有効です。また、テーブルやカラムにエイリアスをつけていると実行計画にもそのエイリアスが出現するので検索しやすく、原因特定の助けになります。

最後に

本当はケーススタディ式に簡単なSQLの実行計画を上述のポイントをおさえながら読み解くところまで書こうと思っていたのですが...。(そして更に難しいSQLで読み解くところも書こうと思っていたのですが...)

...ケーススタディ編は今年度中に書き上げてアップしたいと思います。読んでいただきありがとうございます!本日も皆さんにとって良い一日になりますように!