PostgreSQL Explain は正確に何を教えてくれますか?
-
02-07-2019 - |
質問
MySQL の Explain 出力は非常に単純です。PostgreSQL はもう少し複雑です。それを説明する適切なリソースも見つかりませんでした。
Explain が何を言っているのか正確に説明していただけますか、または少なくとも適切なリソースの方向を教えていただけますか?
解決
説明_EXPLAIN.pdf も役立つかもしれません。
他のヒント
私がいつも混乱するのは、初期費用と総費用の関係です。忘れるたびにグーグルで検索するので、ここに戻ってきますが、違いが説明されていないため、この回答を書いています。これは私がから収集したものです ポストグレ EXPLAIN
ドキュメンテーション, 私が理解しているように説明しました。
以下は、フォーラムを管理するアプリケーションの例です。
EXPLAIN SELECT * FROM post LIMIT 50;
Limit (cost=0.00..3.39 rows=50 width=422)
-> Seq Scan on post (cost=0.00..15629.12 rows=230412 width=422)
PgAdmin からの図による説明は次のとおりです。
(PgAdmin を使用している場合、コンポーネントにマウスを置くとコストの詳細を読むことができます。)
コストはタプルとして表されます。の費用 LIMIT
は cost=0.00..3.39
および順次スキャンのコスト post
は cost=0.00..15629.12
. 。タプルの最初の数値は、 初期費用 2番目の数字は 総費用. 。使ってたので EXPLAIN
そしてそうではありません EXPLAIN ANALYZE
, 、これらのコストは推定値であり、実際の測定値ではありません。
- 初期費用 は難しい概念です。それはそのコンポーネントの前の時間を表すだけではありません 始まります. 。これは、コンポーネントの実行 (データの読み取り) が開始されてから終了するまでの時間を表します。 コンポーネントは最初の行を出力します.
- 総費用 は、データの読み取りを開始してから出力の書き込みを終了するまでの、コンポーネントの実行時間全体です。
複雑なことに、各「親」ノードのコストにはその子ノードのコストが含まれます。テキスト表現では、ツリーはインデントによって表されます。 LIMIT
は親ノードであり、 Seq Scan
その子です。PgAdmin の表現では、矢印は子から親、つまりデータ フローの方向を指します。これは、グラフ理論に精通している人にとっては直観に反するかもしれません。
ドキュメントには、コストにはすべての子ノードが含まれると記載されていますが、親ノードの合計コストに注意してください。 3.39
子の合計コストよりもはるかに小さい 15629.12
. 。のようなコンポーネントが含まれるため、総コストには含まれません。 LIMIT
入力全体を処理する必要はありません。を参照してください。 EXPLAIN SELECT * FROM tenk1 WHERE unique1 < 100 AND unique2 > 9000 LIMIT 2;
の例 ポストグレ EXPLAIN
ドキュメンテーション.
上記の例では、どちらのコンポーネントも行の書き込みを開始する前に処理を行う必要がないため、両方のコンポーネントの起動時間はゼロです。順次スキャンはテーブルの最初の行を読み取り、それを出力します。の LIMIT
最初の行を読み取り、それを出力します。
コンポーネントが行の出力を開始する前に、大量の処理を実行する必要があるのはどのような場合ですか?考えられる理由はたくさんありますが、わかりやすい例を 1 つ見てみましょう。これは前と同じクエリですが、次のクエリが含まれています。 ORDER BY
句:
EXPLAIN SELECT * FROM post ORDER BY body LIMIT 50;
Limit (cost=23283.24..23283.37 rows=50 width=422)
-> Sort (cost=23283.24..23859.27 rows=230412 width=422)
Sort Key: body
-> Seq Scan on post (cost=0.00..15629.12 rows=230412 width=422)
そしてグラフィック的には次のようになります。
もう一度、シーケンシャルスキャンを実行します。 post
初期費用がかかりません:すぐに行の出力を開始します。しかし、このソートには多額の初期コストがかかります 23283.24
そうしなければならないから 単一行を出力する前にテーブル全体をソートする. 。ソートの総コスト 23859.27
これは、データセット全体が一度並べ替えられると、並べ替えられたデータを非常に迅速に出力できるという事実を反映しています。
の起動時間に注目してください。 LIMIT
23283.24
はソートの起動時間とまったく同じです。これは理由ではありません LIMIT
それ自体の起動時間が長いです。実際にはそれ自体の起動時間はゼロですが、 EXPLAIN
各親の子の費用をすべて合計すると、 LIMIT
起動時間には、その子の起動時間の合計が含まれます。
このコストの積み上げにより、個々のコンポーネントの実行コストを理解することが困難になる場合があります。たとえば、私たちの LIMIT
起動時間はゼロですが、一見しただけではわかりません。このため、他の何人かの人々がリンクしました Explain.depesz.com, 、Hubert Lubaczewski (別名: ) によって作成されたツールです。depesz) 理解に役立ちます EXPLAIN
とりわけ、親のコストから子のコストを差し引くことによって。彼は他のいくつかの複雑さについて次のように述べています。 短いブログ投稿 彼の道具について。
インデントが最も多いものから最もインデントが少ないものまで実行され、計画の一番下から一番上まで実行されると思います。(そのため、インデントされたセクションが 2 つある場合、ページのさらに下にあるセクションが最初に実行され、次にそれらのセクションがもう一方のセクションと出会ったときに、それらを結合するルールが実行されます。)
各ステップで 1 つまたは 2 つのデータセットが到着し、何らかのルールによって処理されるという考え方です。データセットが 1 つだけの場合、その操作はそのデータセットに対して実行されます。(たとえば、インデックスをスキャンして必要な行を特定したり、データセットをフィルター処理したり、並べ替えたりします。) 2 つの場合、2 つのデータセットはさらにインデントされた 2 つのものであり、表示されているルールによって結合されます。ほとんどのルールの意味は (特に、これまでにたくさんの説明プランを読んだことがある場合には) かなり簡単に推測できますが、個々の項目を確認するには、ドキュメントを参照するか、(より簡単に) フレーズを投げ込むだけで確認できます。次のようないくつかのキーワードとともに Google EXPLAIN
.
これは明らかに完全な説明ではありませんが、必要な内容を理解できる程度の十分なコンテキストを提供します。たとえば、実際のデータベースからの次の計画を考えてみましょう。
explain analyze
select a.attributeid, a.attributevalue, b.productid
from orderitemattribute a, orderitem b
where a.orderid = b.orderid
and a.attributeid = 'display-album'
and b.productid = 'ModernBook';
------------------------------------------------------------------------------------------------------------------------------------------------------------
Merge Join (cost=125379.14..125775.12 rows=3311 width=29) (actual time=841.478..841.478 rows=0 loops=1)
Merge Cond: (a.orderid = b.orderid)
-> Sort (cost=109737.32..109881.89 rows=57828 width=23) (actual time=736.163..774.475 rows=16815 loops=1)
Sort Key: a.orderid
Sort Method: quicksort Memory: 1695kB
-> Bitmap Heap Scan on orderitemattribute a (cost=1286.88..105163.27 rows=57828 width=23) (actual time=41.536..612.731 rows=16815 loops=1)
Recheck Cond: ((attributeid)::text = 'display-album'::text)
-> Bitmap Index Scan on (cost=0.00..1272.43 rows=57828 width=0) (actual time=25.033..25.033 rows=16815 loops=1)
Index Cond: ((attributeid)::text = 'display-album'::text)
-> Sort (cost=15641.81..15678.73 rows=14769 width=14) (actual time=14.471..16.898 rows=1109 loops=1)
Sort Key: b.orderid
Sort Method: quicksort Memory: 76kB
-> Bitmap Heap Scan on orderitem b (cost=310.96..14619.03 rows=14769 width=14) (actual time=1.865..8.480 rows=1114 loops=1)
Recheck Cond: ((productid)::text = 'ModernBook'::text)
-> Bitmap Index Scan on id_orderitem_productid (cost=0.00..307.27 rows=14769 width=0) (actual time=1.431..1.431 rows=1114 loops=1)
Index Cond: ((productid)::text = 'ModernBook'::text)
Total runtime: 842.134 ms
(17 rows)
自分で読んでみて、意味がわかるかどうかを確認してください。
私が読んだのは、データベースは最初に id_orderitem_productid
インデックス、それを使用して必要な行を検索します orderitem
, 、次に、クイックソートを使用してそのデータセットを並べ替え (データが RAM に収まらない場合、使用される並べ替えは変更されます)、それを脇に置きます。
次にスキャンします orditematt_attributeid_idx
必要な行を見つけるには orderitemattribute
次に、クイックソートを使用してそのデータセットを並べ替えます。
次に、2 つのデータセットを取得して結合します。(マージ結合は、ソートされた 2 つのデータセットを並行して実行し、それらが一致した場合に結合された行を出力する、一種の「圧縮」操作です。)
先ほども言いましたが、計画の内側から外側、下から上へと作業を進めていきます。
PgAdmin 説明計画のグラフィック表現が表示されます。この 2 つを行き来すると、テキスト表現の意味を理解するのに非常に役立ちます。ただし、何を行うのかを知りたいだけの場合は、常に GUI を使用することもできるかもしれません。
PostgreSQL の公式ドキュメント Explain の出力を理解する方法について、興味深く徹底的に説明しています。
pgadmin をインストールすると、[説明] ボタンが表示され、テキスト出力に何が起こっているかを示す図が描画され、フィルター、並べ替え、サブセットのマージが表示され、何が起こっているかを確認するのに非常に役立ちます。