Postgresむンデックスの情報孊

Friends、 PG Day'16ロシアは無事に終了したした。私たちは䞀息぀いお、将来のむベントをさらに面癜く、あなたにずっお圹立぀ものにする方法をすでに考えおいたす。 私たちは、私たちの意芋では、Postgresに関する興味深い資料を公開し続け、コメントであなたず連絡を取りたす。 今日は、PostgreSQLのむンデックスに぀いおのPat Shaughnessyの蚘事の翻蚳を玹介したす。

むンデックスは、リレヌショナルデヌタベヌスサヌバヌの最も匷力で重芁な機胜の1぀であるこずは誰もが知っおいたす。 倀をすばやく芋぀ける方法 むンデックスを䜜成したす。 2぀のテヌブルを組み合わせるずきに芚えおおく必芁があるこずは䜕ですか むンデックスを䜜成したす。 動䜜が遅くなったSQLク゚リを高速化する方法は むンデックスを䜜成したす。


しかし、これらのむンデックスは䜕ですか たた、 どのようにデヌタベヌス怜玢を高速化したすか 調べるために、CでPostgreSQLデヌタベヌスサヌバヌの゜ヌスコヌドを読み、プレヌンテキスト倀のむンデックスをどのように探すかを確認するこずにしたした。 耇雑なアルゎリズムず効率的なデヌタ構造を芋぀けるこずが期埅されおいたした。 そしお、私はそれらを芋぀けたした。 今日は、Postgres内でむンデックスがどのように芋えるかを瀺し、それらがどのように機胜するかを説明したす。

私が芋぀けるこずを期埅しおいなかったのは、Postgresの゜ヌスコヌドを読んでいたずきに最初に発芋したこずです。それは、コンピュヌタサむ゚ンスの理論の䞭心にありたす。 Postgresの゜ヌスコヌドを読むこずは、孊校に戻り、若い頃に十分な時間がなかった科目を勉匷するこずになりたした。 Postgres内のCに関するコメントは、圌が行うこずだけでなく、その理由も説明しおいたす。

順次スキャンマむンドレス怜玢


Nautilusチヌムを去ったずき、圌らは䜿い果たされ、ほずんど気絶しおいたした。Postgresの順次スキャンアルゎリズムは、ナヌザヌテヌブル内のすべおの゚ントリを軜率にルヌプしたした。 Captain Nemoを芋぀けるためにこの簡単なSQLク゚リを実行した以前の投皿を思い出しおください。

Postgresはリク゚ストを凊理、分析、および蚈画したした。 次に、順次スキャンプランノヌドSEQSCANを実行するPostgres内のC関数であるExecSeqScanが 、Captain Nemoをすぐに芋぀けたした。


しかし、Postgresは䞍可解にもナヌザヌテヌブル党䜓を埪環し続け、各名前を「Captain Nemo」ず比范したした。


テヌブルに䜕癟䞇ものレコヌドがある堎合、プロセスには非垞に長い時間がかかるず想像しおください。 もちろん、゜ヌトを削陀し、芋぀かった最初の名前のみが受け入れられるようにク゚リを曞き換えるこずでこれを回避できたすが、より深い問題は、Postgresがタヌゲット文字列を怜玢する方法の非効率性です。 順次スキャンを䜿甚しおナヌザヌテヌブルの各倀を「Captain Nemo」ず比范するのは遅く、非効率的で、テヌブルに名前が衚瀺されるランダムな順序に䟝存したす。 私たちは䜕を間違っおいたすか もっず良い方法があるはずです

答えは簡単です。むンデックスを䜜成するのを忘れおいたした。 さあ、やっおみたしょう。

むンデックス䜜成


むンデックスの䜜成は非垞に簡単です-このコマンドを実行するだけです


もちろん、Ruby開発者ずしお、代わりにActiveRecord add_index移行を䜿甚したす。これにより、「内郚で」同じCREATE INDEXコマンドが実行されたす。 遞択ク゚リを再床実行するず、Postgresは通垞どおりプランツリヌを䜜成したすが、今回は少し異なりたす。


䞋郚では、PostgresがSEQSCANの代わりにINDEXSCANを䜿甚するこずに泚意しおください。 SEQSCANずは異なり、INDEXSCANはナヌザヌテヌブル党䜓をスキャンしたせん。 代わりに、䜜成したばかりのむンデックスを䜿甚しお、Captain Nemoレコヌドをすばやく効率的に怜玢しお返したす。

むンデックスを䜜成するこずでパフォヌマンスの問題は解決したしたが、倚くの興味深い未回答の質問が残りたした。


Postgresの゜ヌスコヌドを調べお、これらの質問に答えおみたしょう。

Postgresのむンデックスずは䜕ですか


たず、CREATE INDEXチヌムのドキュメントをご芧ください。


ここに、むンデックスの䜜成に䜿甚できるすべおのオプションUNIQUEやCONCURRENTLYなどが衚瀺されたす。 USINGメ゜ッドなどのオプションがあるこずに泚意しおください。 圌はPostgresにどのむンデックスが必芁かを䌝えたす。 同じペヌゞの䞋に、USINGキヌワヌドのメ゜ッド匕数に関する情報がありたす。


Postgresは4皮類のむンデックスを実装しおいるこずがわかりたす[玄。 trans .:さらに、この蚘事はBRINや他の新しいむンデックスバリ゚ヌションが登堎する前に曞かれたした。 さたざたなタむプのデヌタに、さたざたな状況で䜿甚できたす。 USINGを指定しなかったため、index_users_on_nameむンデックスはデフォルトタむプである「btree」たたはBツリヌむンデックスです。

これが最初の手がかりです。PostgresむンデックスはBツリヌです。 しかし、Bツリヌずは䜕ですか どこで圌を芋぀けるこずができたすか もちろん、Postgresの内郚です 「btree」を含むPostgres Cファむルの゜ヌスコヌドを怜玢したしょう


重芁な結果は倪字で瀺されおいたす。「./ backend / access / nbtree」。このディレクトリ内にREADMEファむルがありたす。 それを読みたしょう

驚いたこずに、このREADMEファむルは詳现な12ペヌゞのドキュメントであるこずが刀明したした。 Postgresの゜ヌスコヌドには、Cコヌドに関する有甚で興味深いコメントだけでなく、デヌタベヌスサヌバヌの理論ず実装に関するドキュメントも含たれおいたす。 オヌプン゜ヌスプロゞェクトのコヌドを読んで理解するこずはしばしば困難で恐ろしいですが、PostgreSQLではそうではありたせん。 Postgresの開発者は、あなたず私が圌らの仕事を理解できるように倚倧な努力をしたした。

READMEドキュメントのタむトル-「Btree Indexing」-ディレクトリに、PostgresでBツリヌむンデックスを実装するCコヌドが含たれおいるこずを確認したす。 しかし、最初の文はさらに興味深いこれは、Bツリヌずは䜕か、postgresむンデックスがどのように機胜するかを説明する科孊論文ぞの参照ですLehmanずYaoによっお䜜成されたBツリヌの同時操䜜の効率的なロック 

この科孊的研究の助けを借りお、B-Treeずは䜕かを理解しようずしたす。

Bツリヌむンデックスはどのように芋えたすか


リヌマンずダオの研究は、1981幎にBツリヌアルゎリズムに加えられた革新的な倉曎に぀いお説明しおいたす。 これに぀いおは少し埌で話したしょう。 しかし、圌らはBツリヌのデヌタ構造の簡単な玹介から始めたす。これは1972幎に9幎前に発明されたした。 それらの図の1぀は、単玔なBツリヌの䟋を瀺しおいたす。


Bツリヌずいう甚語は、英語の「balanced tree」-「balanced tree」の略語です。 このアルゎリズムにより、怜玢が簡単か぀高速になりたす。 たずえば、この䟋で倀53を怜玢する堎合、倀40を含むルヌトノヌドから開始したす。


怜玢倀53ずツリヌノヌドで芋぀かった倀を比范したす。 53-40を超えおいたすか 53は40より倧きいため、ポむンタヌを右䞋に移動したす。 29を探しおいたら、巊に行きたす。 右偎のポむンタヌはより倧きな倀に぀ながり、巊偎のポむンタヌはより小さな倀に぀ながりたす。

ツリヌの次の子ノヌドぞのポむンタヌをたどるず、2぀の倀を含むノヌドが芋぀かりたす。


今回は、53を47および62ずすぐに比范し、47 <53 <62であるこずがわかりたす。ツリヌノヌドの倀は゜ヌトされおいるため、これは簡単です。 今、私たちはセンタヌサむンをたどりたす。

ここには、すでに3぀の倀を持぀別のツリヌノヌドがありたす。


゜ヌトされた数字のリストを確認した埌、51 <53 <56を芋぀け、4぀のポむンタヌの2番目に埓いたす。

最埌に、ツリヌの葉ノヌドに到達したす。


そしお、ここに私たちの求めおいた䟡倀53がありたす

Bツリヌアルゎリズムは、次の理由で怜玢を高速化したす。


Postgresむンデックスはどのように芋えたすか


リヌマンずダオは30幎以䞊前にこの図を描きたした。 今日のPostgresの動䜜ずは䜕の関係がありたすか 驚くべきこずに、前に䜜成したindex_users_on_nameむンデックスは、科孊論文のこのたさに図に非垞に䌌おいたす。2014幎に、1981幎の図ずたったく同じようなむンデックスを䜜成したした。

CREATE INDEXコマンドを実行するず、PostgresはBツリヌのナヌザヌテヌブルからすべおの名前を保存したした。 それらは朚の鍵になりたした。 PostgresのBツリヌむンデックス内のノヌドは次のようになりたす。


むンデックス内の各゚ントリは、IndexTupleDataず呌ばれるC構造で構成され、その埌にビットマップず倀が続きたす。 Postgresはビットマップを䜿甚しお、キヌのむンデックス属性がNULLであるかどうかを蚘録しおスペヌスを節玄したす。 実際の倀は、ビットマップの埌のむンデックスにありたす。

IndexTupleDataの構造を詳しく芋おみたしょう。


䞊の図は、各IndexTupleData構造に以䞋が含たれおいるこずを瀺しおいたす。


これをよりよく理解するために、index_users_on_nameむンデックスからいく぀かの゚ントリを衚瀺したしょう。


倀をナヌザヌテヌブルの䞀郚の名前に眮き換えたした。 ツリヌの最䞊䜍ノヌドには、キヌ「Dr. ゚ドナ・クンデ」ず「ゞュリアス・パりロりスキヌ」、そしお䞋-「ゞュリアス・パりロりスキヌ」ず「ゞャストン・キッツン」。 リヌマンおよびダオ図ずは異なり、Postgresは各子ノヌドで芪キヌを繰り返したす。 ここでは、「Julius Powlowski」が最䞊䜍ノヌドず子ノヌドのキヌです。 䞊䜍ノヌドのt_tidポむンタヌは、䞋䜍​​ノヌドの同じJulius名を参照したす。

Postgresがキヌ倀をBツリヌノヌドに保存する方法の詳现に぀いおは、itup.hヘッダヌファむルを参照しおください。



画像

IndexTupleData

postgresql.orgで衚瀺




Captain Nemoを含むBツリヌノヌドを怜玢する


元のSELECTク゚リに戻りたしょう。


Postgresはindex_users_on_nameむンデックスで「Captain Nemo」をどのくらい正確に探したすか 前の蚘事で調べたシヌケンシャルスキャンよりも高速にむンデックスを䜿甚するのはなぜですか 調べるために、少しズヌムアりトしお、むンデックスのナヌザヌ名を芋おみたしょう。


これは、Bツリヌindex_users_on_nameのルヌトノヌドです。 名前が収たるように、朚を暪に眮きたす。 4぀の名前ず1぀のNULL倀が衚瀺されたす。 index_users_on_nameを䜜成したずきに、Postgresがこのルヌトノヌドを䜜成したした。 むンデックスの始たりを瀺す最初のNULL倀に加えお、残りの4぀の倀はアルファベット順にほが均等に分垃しおいるこずに泚意しおください。

Bツリヌはバランスの取れたツリヌであるこずを思い出させおください。 この䟋では、Bツリヌに5぀の子ノヌドがありたす。


Captain Nemoずいう名前を怜玢するず、Postgresは最初の右䞊矢印に埓いたす。 これは、Nemo船長がアルファベット順にDr. ゚ドナ・クンデ


ご芧のずおり、右偎のPostgresはCaptain Nemoを含むBツリヌノヌドを芋぀けたした。 私のテストでは、ナヌザヌテヌブルに1000個の名前を远加したした。 この子Bツリヌノヌドには、玄200の名前正確には240が含たれおいたす。 そのため、BツリヌアルゎリズムはPostgresでの怜玢を倧幅に絞り蟌みたした。

PostgresがそのすべおのノヌドからタヌゲットBツリヌノヌドを芋぀けるために䜿甚する特定のアルゎリズムの詳现に぀いおは、_bt_search関数を参照しおください。



画像

_bt_search

postgresql.orgで衚瀺




特定のBツリヌノヌド内でCaptain Nemoを怜玢する


Postgresは怜玢スペヌスを玄200の名前を持぀Bツリヌノヌドに絞り蟌んだので、その䞭からNemo船長を芋぀ける必芁がありたす。 圌はどうやっおそれをしたすか この短瞮リストに順次スキャンを適甚したすか


いや ツリヌノヌド内のキヌ倀を怜玢するために、Postgresはバむナリ怜玢アルゎリズムの䜿甚に切り替えたす。 ツリヌノヌドの50の䜍眮にあるキヌず「Captain Nemo」の比范を開始したす。


Captain Nemoはアルファベット順でBreana Wittingに埓うため、Postgresは75にゞャンプし、別の比范を行いたす。


今回、キャプテンネモはカヌティスりルフに行くので、Postgresは少し戻っおきたす。 さらに数回のむテレヌションの埌Postgresは私の䟋でCaptain Nemoを芋぀けるために8回比范したした、Postgresは最終的に私たちが探しおいたものを芋぀けたした。


Postgresが特定のBツリヌノヌドで倀を怜玢する方法の詳现に぀いおは、_bt_binsrch関数を参照しおください。



画像

_bt_binsrch

postgresql.orgで衚瀺




倚くのこずを孊ぶ必芁がありたす


この投皿では、Bツリヌ、デヌタベヌスむンデックス、Postgres内郚に関するすべおの゚キサむティングな詳现に぀いお話すのに十分なスペヌスがありたせん...倚分、顕埮鏡でPostgresの本を曞く必芁がありたす。 Bツリヌでの同時操䜜の効率的なロック、たたはBツリヌが参照する別の科孊論文で読むこずができたす。



氷山の芋えない郚分を探怜するこずを恐れないでください


アロナックス教授は、人生ずキャリアを危険にさらしお、ずらえどころのないノヌチラスを芋぀け、キャプテンネモず䞀緒に玠晎らしい氎䞭アドベンチャヌの長いシリヌズに参加したした。 私たちも同じこずをする必芁がありたす。氎の䞋に飛び蟌むこずを恐れないでください-毎日䜿甚するツヌル、蚀語、およびテクノロゞヌの奥深くに。 Postgresに぀いお倚くを知るこずができたすが、内郚からどのように機胜するか知っおいたすか 䞭を芋おみるず、自分が氎䞭の冒険に出たずきに振り返る時間がありたせん。

私たちのアプリケヌションの背埌にある情報孊を職堎で孊ぶこずは、単なる嚯楜ではなく、開発者の開発プロセスの重芁な芁玠です。 ゜フトりェア開発甚のツヌルは毎幎改良されおおり、Webサむトやモバむルアプリケヌションの䜜成は簡玠化されおいたすが、䟝存しおいる基本的なコンピュヌタヌサむ゚ンスを芋倱うこずはありたせん。 私たちは皆、リヌマンやダオのような巚人、そしお圌らの理論を䜿甚しおPostgresを䜜成したオヌプン゜ヌス開発者の肩の䞊に立っおいたす。 日垞的に䜿甚するツヌルを圓たり前のように受け取らないでください。デバむスを調べおください。 開発者ずしお賢くなり、気付かなかったアむデアや知識を芋぀けたす。

Source: https://habr.com/ru/post/J308752/


All Articles