クエリの最適化。 PostgreSQLの基本を説明する



リクエストにそれほど時間がかかったのはなぜですか? インデックスが使用されないのはなぜですか?

おそらく誰もがPostgreSQLでEXPLAINを聞いたことがあるでしょう。 しかし、その使い方を理解している人は多くありません。 彼自身は長い間、理解しやすい教科書を見つけることができませんでした(検索が不十分ですか?)。

この素晴らしいツールに対処したい人にこの記事が役立つことを願っています。



これは翻訳ではなく、著者による資料の処理です。ギヨーム・レラージのEXPLAIN理解しています。 情報の一部が省略されているため、オリジナルを読むことを強くお勧めします。



そんなに怖くない



クエリを最適化するには、PostgreSQLカーネルの背後にあるロジックを理解することが非常に重要です。

説明しようとします。 実際、すべてがそれほど複雑ではありません。 EXPLAINは、カーネルが各特定のリクエストで何をするかを理解するために必要な情報を表示します。 EXPLAINコマンドの出力を並行して検討し、PostgreSQLの内部で何が起こっているのかを理解します。 これは、PostgreSQL 9.2以降に適用されます。



私たちのタスク:






最初のステップ



100万行のテストパターンでを訓練します

CREATE TABLE foo (c1 integer, c2 text); INSERT INTO foo SELECT i, md5(random()::text) FROM generate_series(1, 1000000) AS i;
      
      





データを読み取ってみましょう

 EXPLAIN SELECT * FROM foo;
      
      





クエリプラン

-fooのSeqスキャン(コスト= 0.00..18334.00行= 1,000,000幅= 37)

(1行)



テーブルからデータを読み取るには、いくつかの方法があります。 この場合、EXPLAINは、 Seq Scan



が使用されていることを報告します-順次、ブロックfoo



foo



テーブルからのデータの読み取り

cost



とは? これは時間ではありませんが、操作のコストを評価するために設計された、ある種の真空コンセプトの球状です。 最初の値0.00



は、最初の行を取得するコストです。 2番目18334.00



すべての行を取得するコスト。

rows



は、 Seq Scan



操作の実行時に返されるおよその行数です。 この値は、スケジューラーによって返されます。 私の場合、テーブルの実際の行数と一致します。

width



-1行の平均サイズ(バイト単位)。

10行追加してみましょう。

 INSERT INTO foo SELECT i, md5(random()::text) FROM generate_series(1, 10) AS i; EXPLAIN SELECT * FROM foo;
      
      





クエリプラン

-fooのSeqスキャン(コスト= 0.00..18334.00行= 1,000,000幅= 37)

(1行)



rows



の値は変更されrows



いません。 テーブルの統計は古いです。 統計を更新するには、 ANALYZE



コマンドを呼び出します。

 ANALYZE foo; EXPLAIN SELECT * FROM foo;
      
      





クエリプラン

-fooのSeqスキャン(コスト= 0.00..18334.10行= 1000010幅= 37)

(1行)



rows



に正しい行数が表示されるようになりました。



ANALYZEを実行するとどうなりますか?




ANALYZEが読み込む行数は、 default_statistics_target



パラメーターによって異なります。



実データ


EXPLAINコマンドの出力で上で見たのは、スケジューラの期待だけです。 それらを実際のデータの結果と比較してみましょう。 EXPLAIN (ANALYZE)



を使用します。

 EXPLAIN (ANALYZE) SELECT * FROM foo;
      
      





クエリプラン

-fooのSeqスキャン(コスト= 0.00..18334.10行= 1000010幅= 37)(実際の時間= 0.012..61.524行= 1000010ループ= 1)

合計ランタイム:90.944ミリ秒

(2行)



そのような要求は現実的に実行されます。 したがって、INSERT、DELETE、またはUPDATEについてEXPLAIN(ANALYZE)を実行すると、データが変更されます。 注意してください! そのような場合は、ROLLBACKコマンドを使用してください。

コマンド情報の出力が追加されました。

actual time



-最初の行とすべての行をそれぞれ取得するために費やされたリアルタイム(ミリ秒単位)。

rows



- Seq Scan



受信した実際の行数。

loops



-操作Seq Scan



を実行しなければならなかった回数。

Total runtime



-リクエストの合計ランタイム。



もっと...


最初の部分については、おそらく十分でしょう。

パート2

パート3



All Articles