Kapila氏に向かいました。彼のこのトピックのブログエントリには、一読の価値があります。ハッシュindexの問題は、先読みログのコードを書くのが面倒だっただけではなく、実際に正しく動作するような先読みログを追加できるようにコードが構成されていないことでした。バケットを分割するには、システムは既存のバケットをロックし(かなり非効率なロック機構を使用)、タプルの半分を新しいバケットに移動し、既存のバケットを圧縮してロックをリリースします。個々の変更が記録されたとしても、間違ったタイミングでクラッシュすると、indexが破損した状態になる可能性があります。そこで、Amit氏の最初のステップは、ロック機構を再設計することでした。新しいメカニズムにより、スキャンとスプリットがある程度並行して進行し、エラーやクラッシュによって中断された分割を後で完了することができます。バグが修正され、いくつかのリファクタリング作業が完了すると、Amit氏のもう1つのpatchにハッシュindexesの先読みログサポートが追加されました。ところで、ここ数年でbtreeに加えられた多くの比較的わかりやすいパフォーマンスの改善項目において、ハッシュインデックスが落ちている事がわかりました。ハッシュインデックスは先行書き込みログではサポートされておらず、古いロック機構が非常に重いものであったため、さらにパフォーマンスを改善させたいと言うモチベ―ションがあまりなかったのです。これはハッシュインデックスが真に有効なテクノロジーであったのであれば、単に先行書き込みログを追加する以外に他に実行すべきことがあった事を意味します。PostgresSQLのインデックスアクセス方式の抽象化レイヤーは、インデックスによって、インデックスに関する情報のバックエンドプライベートキャッシュを保持する事が可能であり、インデックス自体は所定のメタデータを取得するために繰り返して参照される必要はありません。このメカニズムを使って、ハッシュインデックスのメタページをキャッシュするパッチを書きました。同様に、btreeインデックスはインデックスページから不用なインデックスポインターを日和見的に削除し、放置すると発生する可能性のある膨大な量のインデックスの膨張を回避する、「シングルページ真空化」と呼ぶ最適化を持っています。ハッシュインデックス上にポート化するパッチを書き、そこでの同様のインデックスの膨張を画期的に減らしました。btreeのインデックスは、同一のインデックスページが繰り返しロックおよびアンロックされる事を防止する機能を持ち、代わりにページから一回でタプルをスラープし、一度に一つづつ返すようにしました。ハッシュインデックスにポートしましたが、時間が足らずに最適化はv10には採用されませんでした。このブログ内容に述べられている全体の内、v11までに実現しない唯一の改善はこれのみです。ハッシュインデックス関連でより興味深い側面の1つに、動作が実際に正しいのかを決定する際の困難さがあります。ロック動作に関する変更は、並列処理が多用される場合にのみ失敗しますが、クラッシュ回復の場合には先行書き込みログのバグが、恐らくは唯一の兆候です。各ケースごとに、問題は捉えにくいものです。物事がクラッシュなしで走っていると言うだけでは十分ではありません。あらゆる場面で正しい答えが作成されなくてはならず、これが検証する事が難しいのです。PostgresSQLに注力した、WAL一貫性チェッカーを作成しました。ハッシュインデックスの先行書き込みログコードは、コミットする前にこのツールを使って徹底的にテストされ、バグの発見に非常に効果がありました。このツールはハッシュインデックスのみに限りません:ヒープ、今日我々が持つ全てのインデックスAM、そして将来開発されるその他のものを含めて、他モジュール用の先行書き込みログコードの妥当性検証にも使用することができます。BRINのバグを発見する事に成功しています。wal_consistency_checkingは、主に開発者用ツールですが、バグが疑われる場合にもユーザーが使用するのに適しています。そこでは、DBA向けのいくつかのツールもアップグレードがなされました。contribモジュールをアップグレードするpatchを書きました(それは本当に良いアイデアでした。これらのテストケースは即座に失敗したため、数回のバグ修正を引き起こしました)。Sharma氏の作業により、ハッシュindexesのためのサポートを得ています。その途中で、パフォーマンスの改善もいくつかありました。私が最初に気づいていなかったことの1つは、ハッシュindexesがバケット分割の新しいラウンドを開始すると、ディスク上のサイズが急激に倍増する傾向があることでした。これは、実際には1MBのindexでは問題にはなりませんが、64GBのindexがあるとその限りではありません。Cy氏は、倍増を4段階に分けるためのpatchを書いてこの問題をある程度解決しました。64GBから128GBに一気に変わるのではなく、64GBから80GB、96GB、112GB、そして128GBへと小刻みに変わるようにします。これは、さらに改善することができますが、ディスク上のフォーマットをより深く再構築し、検索パフォーマンスへの影響を注意深く考慮する必要があります。7月の「AP」に参加したテスターからの報告書は、いくつかの調整が必要であることを私たちに教えてくれました。APは、新しく作成されたハッシュindexに20億行を挿入しようとすると、エラーが発生することを発見しました。この問題に対処するために、Amit氏は各分割の直後に古いバケットのクリーンアップを試みるようにバケット分割コードを修正し、オーバーフローページの蓄積を大幅に削減しました。念のために、Amit氏と私は、オーバーフローページの割り当てを追跡するために使用されるビットマップページの最大数を4倍に増やしました。それ以外にもいろいろなことをなすこともできましたが、同僚と私は、PostgreSQLコミュニティの他のメンバーの助けを借りて、ハッシュindexesを、放置され、間違いのある未熟な機能ではなく、一級品の機能にするという目標を達成しました。その機能のユースケースがどのようなものであるかはよく分かります。この記事の冒頭で私が参照(リンク)したAmit氏のブログエントリーは、pgbench作業負荷であっても、ハッシュindexは、低レベルと高レベルの並行処理の両方でbtreeを上回る可能性があることを示しています。それは、実際には最悪のケースです。ハッシュindexesのセールスポイントの1つは、indexに実際の索引をつけた値ではなくハッシュ値が格納されていることです。そのため、UUIDや長い文字列などの幅の広いキーでは、改善が大きくなると予想しています。それについては、私たちが読み込みと同じ程度の書き込みを最適化していないため、読み込み負荷の高い作業負荷でより力を発揮する傾向があります。私はこの技術に興味を持っている人には、それを試してメーリングリストに結果を投稿する(または個人的にメールを送る)ようお勧めします。このような機能の本当の鍵は、開発者が実験室で起こる性質のものではなく、現場で実際に起こることだからです。Pedersen氏に、このプロジェクトと一般の両方に関連した貴重なテスト作業を行っていただいたことに心から感謝したいと思います。この規模のプロジェクトを正確に取得することは簡単ではなく、破壊的な要素をなくすと決心した粘り強いテスターを持つことは、大きな助けになります。Horiguchi氏。皆さん、本当にありがとうございました。表記し忘れてしまった方がいましたら、彼らにもまた感謝の気持ちを捧げたいと思います。Haasは、EnterpriseDBの副社長であり、チーフデータベースアーキテクトです。この投稿記事は、もともとRobert氏の個人的なブログに掲載されていたものです。