1

関連する部分の私のデータベーススキーマは、ブールフィールドAdminを持つUserというテーブルがあります。このフィールドAdminにインデックスがありました。

完全な本番データベースを開発マシンに復元し、データベースにごくわずかな変更を加えただけだったので、それらは非常に似ているはずでした。

開発マシンで次のコマンドを実行すると、期待どおりの結果が得られました。

EXPLAIN SELECT * FROM user WHERE admin IS TRUE;

Index Scan using index_user_on_admin on user (cost=0.00..9.14 rows=165 width=3658)
Index Cond: (admin = true)
Filter: (admin IS TRUE)

ただし、実稼働マシンでまったく同じコマンドを実行すると、次のようになります。

Seq Scan on user  (cost=0.00..620794.93 rows=4966489 width=3871)
Filter: (admin IS TRUE)

したがって、クエリに完全に一致する完全なインデックスを使用する代わりに、約500万行のシーケンシャルスキャンを使用していました。

EXPLAIN ANALYZE SELECT * FROM user WHERE admin IS TRUE;次に、Postgresに500万行のシーケンシャルスキャンがインデックスを使用するほど良くないことを認識させることを期待して実行しようとしましANALYZEたが、それでも何も変わりませんでした。

REINDEX INDEX index_user_on_adminまた、インデックスが破損した場合に備えて、何のメリットもなく実行しようとしました。

最後に、私は電話VACUUM ANALYZE userをしました、そしてそれは短い順序で問題を解決しました。

真空についての私の主な理解は、それが無駄なスペースを取り戻すために使用されるということです。何が起こっていたので、インデックスの動作が非常に悪くなり、なぜ掃除機で修正されたのでしょうか。

4

4 に答える 4

5
  1. ANALYZEプランナーが使用するデータ統計を更新して、クエリを実行するための最良の方法を決定することで、それが役に立った可能性が最も高いです。VACUUM ANALYZE2つのコマンドをVACUUM最初、ANALYZE2番目の順序で実行するだけですが、ANALYZEそれ自体で十分に役立つ可能性があります。

  2. ANALYZEオプションは、コマンドEXPLAINとはまったく関係ありません。ANALYZEこれにより、Postgresはクエリを実行し、実際の実行時間を報告するため、プランナーの予測と比較できます(クエリプランとプランナーがコストと考えるものだけを表示せずに、実際にはクエリを実行しませんEXPLAINANALYZEEXPLAIN ANALYZEそれは統計を更新しなかったので、それで助けにはなりませんでした。ANALYZEEXPLAIN ANALYZEはまったく異なる2つのアクションであり、たまたま同じ単語を使用しています。

于 2012-09-01T22:02:59.157 に答える
2

PostgreSQLは、テーブルの状態、インデックスの状態、データなどに関する多くの高度な統計を保持しています...これは時々同期しなくなる可能性があります。実行VACUUMすると問題が修正されます。

開発時にテーブルを最初からリロードした場合も、同じ効果があった可能性があります。

これを見てください:

http://www.postgresql.org/docs/current/static/maintenance.html#VACUUM-FOR-STATISTICS

于 2012-09-01T20:33:39.923 に答える
1

部分インデックスは、問題の良い解決策のようです。

CREATE INDEX admin_users_ix ON users (admin)
    WHERE admin IS TRUE;;

同じフィールドで多くのタプルにインデックスを付ける意味はありません。

于 2012-09-01T22:30:44.403 に答える
1

これが私が最も可能性の高い説明だと思うものです。

インデックスは、返される行数が非常に少ない場合にのみ役立ちます(ところで、この理由でboolにインデックスを付けるのは好きではありません。代わりに部分インデックスを使用するか、whereadminがtrueになるように追加することを検討してください。とにかく使用できる可能性が高い場合にのみインデックスを保持してください)。

テーブル内のページの10%以上を取得する場合、プランナーは、少量のランダムディスクI / Oではなく、大量のシーケンシャルディスクI/Oを選択する可能性があります。大皿が回るのを待つ必要があります。そこではシーク速度が大きな問題であり、PostgreSQLはそれとリレーションから取得される実際のデータの量とのバランスをとろうとする傾向があります。

テーブルが以前よりも小さいか、ユーザーの一部として管理者が多かったことを示す統計が収集されたため、プランナーは不適切な情報を使用して決定を下しました。

VACUUMANALYZEは3つのことを行います。まず、トランザクションのラップアラウンドが問題にならないように、すべてのトランザクションに表示されるタプルをフリーズします。次に、トランザクションに表示されないタプルを空き領域として割り当てます。これらのどちらもあなたの問題に影響を与えませんでした。ただし、3つ目は、テーブルを分析し、テーブルの統計を収集することです。これはランダムサンプリングであるため、オフになる場合があることに注意してください。私の推測では、前回の実行では、多くの管理者がいるページを取得したため、システムの管理者の数を大幅に過大評価していました。

統計が他の場所で非常に古くなっている可能性もあるため、これはおそらく自動真空設定を再確認する良い機会ですが、それは確実ではありません。特に、コストベースのバキューム設定にはデフォルトがあり、バキュームが完全に追いつかない場合があります。

于 2012-09-02T02:04:24.523 に答える