sql >> データベース >  >> RDS >> PostgreSQL

PostgreSQLでのヒント

    今週のpgsql-performanceリストでの炎上戦争は、PostgreSQLが他のデータベースで利用できる従来のヒント構文を持っていないという事実を中心に再び展開しています。その理由の背後には、技術的な理由と実用的な理由が混在しています。

    • ヒントの導入は、後の問題の一般的な原因です。これは、特殊なケースでクエリの場所を1回修正することは、それほど堅牢なアプローチではないためです。データセットが大きくなり、場合によっては分布も変化するにつれて、データセットが小さかったときに示唆したアイデアは、ますます悪いアイデアになる可能性があります。
    • 便利なヒントインターフェイスを追加すると、オプティマイザコードが複雑になり、そのまま維持するのは困難です。 PostgreSQLがクエリの実行と同様に機能する理由の一部は、データベースの作成に関して、実際には費用がかからない快適なコード(「ベンダー比較機能リストでヒントを確認できます!」)があるためです。継続的なメンテナンスを正当化するのに十分なほど、ポリシーによって拒否されます。動作しない場合、追加されません。そして、客観的に評価すると、ヒントは平均して解決策ではなく問題になります。
    • ヒントが機能するような問題は、オプティマイザーのバグである可能性があります。 PostgreSQLコミュニティは、オプティマイザの真のバグに業界の他の誰よりも早く対応します。周りに聞いてみると、バグを報告して翌日までに修正されるのを見る前に、多くのPostgreSQLユーザーに会う必要はありません。

    さて、ヒントを見つけるための主な完全に有効な応答は、通常はそれらに慣れているDBAから欠落しています。「オプティマイザーのバグに遭遇した場合、どうすれば対処できますか?」今日のすべての技術作業と同様に、悪いクエリの問題が発生した場合、通常、可能な限り迅速な修正を取得するという大きなプレッシャーがあります。
    PostgreSQLにその状況に対処する方法がなければ、本格的なPostgreSQLデータベースはありません。 。違いは、このデータベースで調整することは、オプティマイザーが何をすべきかを指示するだけでなく、オプティマイザーがすでに行っている決定に影響を与えることに根ざしていることです。これらは文字通りの意味でのヒントであり、PostgreSQLを初めて使用する他のデータベースのユーザーが探しに行くことを示唆するためのユーザーインターフェイスがないだけです。
    それを念頭に置いて、何を見てみましょう。 PostgreSQLで実行して、悪いクエリプランやオプティマイザのバグを回避できます。特に、多くの人が考えていることは、ヒントでしか解決できないと思われます。

    • join_collapse_limit:これは、オプティマイザーが複数のテーブルの結合を並べ替える際に必要な柔軟性を調整します。通常、結合を再配置できる場合は、可能なすべての組み合わせを試行します(外部結合を使用している場合を除き、ほとんどの場合です)。 join_collapse_limitをおそらく1に下げると、この柔軟性の一部またはすべてが失われます。 1に設定すると、期間内に書き込んだ順序で結合が取得されます。多数の結合を計画することは、オプティマイザーが実行するのが最も難しいことの1つです。各結合は見積もりの​​エラーを拡大し、クエリの計画時間を増やします。データの基本的な性質により、どの順序の結合が発生するかが明確になり、それが変わることはないと思われる場合は、正しい順序を見つけたら、このパラメーターを使用してデータをロックダウンできます。
    • random_page_cost:デフォルトで4.0の場合、このパラメータは、参照値1.0と比較して、ディスク上でランダムなページを見つけるためにディスクを探すのにかかる費用を設定します。さて、実際には、通常のハードドライブでランダムI /OとシーケンシャルI/Oの比率を測定すると、この数値は50に近いことがわかります。では、なぜ4.0なのですか?まず、コミュニティテストでは、より大きな値よりもうまく機能しているためです。第2に、多くの場合、特にインデックスデータはメモリにキャッシュされるため、これらの値を読み取るための実効コストが低くなります。たとえば、インデックスがRAMに90%キャッシュされている場合、それは10%の時間で50倍のコストがかかる操作を実行することを意味します。これにより、効果的なrandom_page_costは約5になります。このような実際の状況が、デフォルトが現在の場所で意味をなす理由です。私は通常、人気のあるインデックスがメモリ内で95%を超えるキャッシュを取得するのを目にします。インデックスが実際にすべてRAMにある可能性が高い場合は、random_page_costを1.0を少し超えるまで下げるのが妥当な選択です。これは、他のどの読み取りよりもコストがかからないことを反映しています。同時に、非常にビジーなシステムでのランダムシークは、シングルユーザーシミュレーションを見るだけで予想されるよりもはるかにコストがかかる可能性があります。プランナーがインデックスのコストを誤って見積もっていたときにデータベースがインデックスの使用を停止するようにするには、random_page_costを60まで高く設定する必要がありました。通常、この状況は、プランナー側の感度見積もりエラーに起因します。テーブルの約20%以上をスキャンしている場合、プランナーは、シーケンシャルスキャンの使用がインデックススキャンよりもはるかに効率的であることを知っています。プランナーが行の1%が返されることを期待したときよりもはるかに早くその動作を強制しなければならなかったという醜い状況が発生しましたが、実際には15%に近かったです。
    • work_mem:並べ替え、ハッシュ、および同様のメモリベースの操作を実行するクエリで使用できるメモリの量を調整します。これはクエリの大まかなガイドラインであり、ハード制限ではありません。単一のクライアントがクエリの実行時に複数のwork_memを使用する可能性があります。したがって、postgresql.confファイルでこの値を高く設定しすぎないように注意する必要があります。ただし、代わりにできることは、クエリを実行する前に設定することです。これは、並べ替えやハッシュデータを保持するための追加のメモリがあることで実際にメリットがあります。 log_min_duration_statementを使用して、遅いクエリをログに記録することで、これらのクエリを見つけることができる場合があります。 log_temp_filesをオンにすることでそれらを見つけることもできます。これは、work_memが小さすぎるたびにログに記録されるため、並べ替え操作がメモリ内ではなくディスクに流出します。
    • オフセット0:PostgreSQLはサブクエリを結合の形式に再配置するため、通常の結合順序ロジックを使用して最適化できます。場合によっては、サブクエリとして人々が書く傾向があるようなものは、何らかの理由で推定するのが少し難しいように見えるため、その決定は本当に悪いものになる可能性があります(私が見るそのような厄介なクエリの数に基づいて言います)。このロジックを防ぐために実行できる卑劣なトリックの1つは、サブクエリの最後にOFFSET0を配置することです。これによって結果が変わることはありませんが、OFFSETの実行に使用されるLimitクエリノードのタイプを挿入すると、再配置が防止されます。その後、サブクエリは常に、ほとんどの人が期待する方法で、独自の分離されたクエリノードとして実行されます。
    • enable_seqscan、enable_indexscan、enable_bitmapscan:テーブル内の行を検索するためにこれらの機能のいずれかをオフにすることは、そのタイプのスキャンを回避することを強くお勧めします(計画を実行する方法がない場合は、常に阻止するわけではありませんが、 seqscanの場合、パラメーターがオフになっている場合でもseqscanを取得します)。私がこれらをお勧めする主なことは、クエリを修正することではなく、EXPLAINを試して、他のタイプのスキャンが好まれた理由を確認することです。
    • enable_nestloop、enable_hashjoin、enable_mergejoin:テーブルの読み取り方法ではなく、使用されている結合のタイプが問題であると思われる場合は、これらのパラメーターのいずれかを使用して、プランに表示されているタイプをオフにしてから、EXPLAINを実行してください。また。感度の見積もりに誤りがあると、結合の効率が実際よりも多少高くなる可能性があります。また、現在の結合方法を無効にした状態で計画がどのように変化するかを確認することは、そもそもその方法を決定した理由について非常に有益です。
    • enable_hashagg、enable_material:これらの機能はPostgreSQLにとって比較的新しいものです。ハッシュアグリゲーションの積極的な使用はバージョン8.4で導入され、より積極的なマテリアライゼーションは9.0で導入されました。 EXPLAIN
      出力にこれらのタイプのノードが表示されていて、それらが間違っているように見える場合、このコードは非常に新しいため、古い機能の一部よりも制限やバグがある可能性が少し高くなります。古いバージョンのPostgreSQLで正常に機能したが、これらのノードタイプのいずれかを使用していて、結果としてパフォーマンスが大幅に低下しているように見えるプランがある場合、これらの機能を無効にすると、以前の動作に戻るだけでなく、光を当てることができます。オプティマイザーが有用なフィードバックとして間違ったことをした理由。これは通常、より高度な機能がPostgreSQLに導入される傾向があることに注意してください。以前のバージョンの実行方法に比べて計画が後退していることが判明した場合は、トラブルシューティングの目的でオフにするオプションがあります。
    • cursor_tuple_fraction:クエリからすべての行を読み戻す予定がない場合は、カーソルを使用してそれを実装する必要があります。その場合、オプティマイザーは、このパラメーターに基づいて、最初の行をすばやく戻すか、クエリ全体を最適化するかを優先しようとします。デフォルトでは、データベースは、カーソルを使用したときにクエリの10%を再度読み取ると想定しています。このパラメータを調整すると、それよりも少ないまたは多い読み取りを期待するようにバイアスをかけることができます。

    これらのパラメータとクエリの微調整はすべて、トリアージの調整を考慮する必要があります。これらを永久に配置したまま実行することは望ましくありません(おそらくjoin_collapse_limitを除く)。それらを使用してジャムから抜け出し、うまくいけば、悪い計画の本当の根本的な原因(悪い統計、オプティマイザーの制限/バグなど)を理解し、その方向から問題に対処します。オプティマイザーの動作をある方向にプッシュすればするほど、データの将来の変更にさらされる可能性が高くなり、そのプッシュは正しいものではなくなります。それらを正しく使用すると、間違った計画(PostgreSQL 9.0 High Performanceのクエリ最適化の章で使用したアプローチ)を研究する方法として、PostgreSQLで物事を示唆する方法で、すべての実行を終了する必要があります-オプティマイザの動作が悪いと、将来そのクラスの問題を回避する方法についてもう少し慎重になります


    1. MySQLでインデックス付きビューを作成することは可能ですか?

    2. ODBC接続を使用したExcelVBAマクロからのOracleテーブルの更新

    3. MySQLでデータベースの照合を表示する方法

    4. mssqlモジュールを使用してNode.JSからWindows認証でSQLServerに接続する方法