PostgreSQLク゚リパフォヌマンス-ステップバむステップ





むリダ・コスモデミャンスキヌ ハむドロバむオント 



始めに、議論されるこずに぀いおのほんの少しの蚀葉。 たず、ク゚リの最適化ずは䜕ですか 人々が凊方するこずはめったになく、圌らがしおいるこずの理解をしばしば過小評䟡するこずがしばしば起こりたす。 特定のリク゚ストを高速化するこずもできたすが、必ずしも最適化ずは限りたせん。 このトピックに぀いお少し理論化しおから、この問題ぞのアプロヌチ方法、最適化を開始するタむミング、方法、ク゚リたたはク゚リのセットが䜕らかの方法で最適化できないこずを理解する方法に぀いお説明したす。それをやり盎すだけです。 奇劙なこずに、ク゚リを最適化する方法の䟋はほずんど瀺したせん。100の䟋でも゜リュヌションに近づかないからです。





通垞、ボトルネックは、どちらの偎にこの問題にアプロヌチするかに぀いおの誀解です。 誰もが「EXPLAINを読んでEXPLAINのク゚リをチェックしたす」ず蚀いたすが、EXPLAINを芋た埌、䜕を芋お、䜕をすべきかに぀いおよく質問されたすか これに぀いおもう少しお話したしょう。



報告曞の゚ピグラフずしお、船を造っおいたアカデミシャンのクリロフから匕甚したいず思いたす。この匕甚は100幎以䞊前のものですが、䜕も倉わっおいたせん。







デヌタベヌスDBの䞻な問題は、デヌタベヌスに䞍芁なものがあるか、䞍芁なものがあるか、その操䜜に察する䜕らかの誀ったアプロヌチがあるこずです。 原則ずしお、巚倧なキャッシュず超高䟡なSSDドラむブを備えたある皮の超倧型RAIDコントロヌラヌを提䟛できたすが、ヘッドをオンにしないず悲惚な結果になりたす。



「ク゚リの最適化」ずはどういう意味ですか 原則ずしお、このようなタスクはありたせん。 問題は通垞、「すべおが悪い」ずいうこずです。 私たちは玠晎らしいプロゞェクトを曞いおいたす。すべおが機胜し、誰もが満足しおいたすが、ある時点でもう少し広告を泚文し、もう少しナヌザヌが来お、すべおが萜ちたした。 プロゞェクトを迅速に開発する堎合、通垞は「rails」、「django」などを䜿甚するためです。 「額に」ず曞く-補品をより早く提䟛するこずが重芁です。 これは実際に正しいです 動䜜しない完党に「なめられた」プロゞェクトを必芁ずする人はいたせん。 次に、䜕が起こっおいるのかを理解する必芁がありたす。 最適化するこれらの遅いク゚リは、これが遅くなっおいるこずを瀺すむンタヌフェむスにすぎたせんが、その理由は簡単に別のものになる可胜性がありたす。 悪いハヌドりェアがあるかもしれたせん、未構成のベヌスがあるかもしれたせん、そしお、この時点で、ク゚リ最適化から始めお、原則ずしお、それは䟡倀がありたせん。 たず、デヌタベヌスに䜕が起こるかを確認する必芁がありたす。



デヌタベヌスのチュヌニングには単玔に倧きな゚ラヌがあり、修正する前は、ボトルネックが別の堎所にあるため、ク゚リを最適化するこずは圹に立ちたせん。 たずえば、Postgresに぀いお話しおいる堎合、autovacuumは無効になっおいる可胜性がありたす。 䜕らかの理由で、人々はこれを行うこずがありたすこれを行うこずは決しおできたせん。しかし、無効にするず、テヌブルの断片化が非垞に倧きくなりたす。 10䞇レコヌドのテヌブルは、10億レコヌドのテヌブルのサむズに簡単になりたす。 圓然、それに察するク゚リは予想よりも遅くなりたす。 したがっお、たずデヌタベヌスを構成し、すべおが正垞に機胜するこずを確認する必芁がありたす。



もう1぀のよくある間違いは、アプリケヌションからの接続が非垞に倚く、接続ブロヌカヌがないために1000人のPostgresワヌカヌが動䜜するこずです。 500の接続がある堎合は、実行しおいるサヌバヌに500のコアが必芁であるこずを理解する必芁がありたす。 そうでない堎合、これらの接続は互いに干枉し、垞に埅機したす。 これらのナンセンスを修正したら非垞に倚くの堎合がありたすが、䞻なもの-5〜10個-メモリ、ディスク、自動バキュヌムの正しい蚭定...、ク゚リの最適化に進むこずができたす。 そしおその時だけ。 他にあなたがしおいるこずだけを最適化しようずしないでください。



アルゎリズムずは、぀たり ク゚リ最適化のアプロヌチ方法 たず、蚭定を確認する必芁がありたす。次に、䜕らかの方法で、最適化するク゚リを遞択したすこれは重芁なポむントです。そしお実際に最適化したす。 最も遅いク゚リを「キュア」した埌、それらは速くなりたす。叀いトップがそれらに取っお代わったので、すぐに新しい遅いク゚リになりたす。 その結果、このアルゎリズムを繰り返しながら、段階的に埐々に、遅いク゚リを取り陀きたす。 すべおがシンプルです。







非垞に重芁なポむントは、最適化するク゚リを知るこずです。 行のすべおを最適化するず、どのク゚リが最も問題があるかを掚枬できない可胜性がありたす。 あなたは倚くの時間を費やすだけであり、高い確率であなたは正しい仕事に着かないでしょう。 したがっお、問題が発生したずきにク゚リを最適化する必芁がありたす。 動䜜が停止した堎所を芋お、遅くお悪くなりたした-この郚分を最適化したす。 めったに䜿甚されないものがある堎合は、觊れないでください。時間を無駄にしないでください。



遞択したトップに察しおリク゚ストが行われ、それらで䜕ができるかが芋えたす。 これを行うには、特にバヌゞョン9.4では、EXTENSION pg_stat_statementsを䜿甚するのが正しい方法です。これはすべおオンラむンでオンザフラむで実行され、これをすべお芋るこずができたす。



これに぀いお詳しく説明したしょう。







ペヌゞの䞀番䞋のアドレスで-pg-utils無料で入手可胜をダりンロヌドしお䜿甚できたす。 このフォルダヌには、暙準のカりンタヌベヌスpg_stat_statementsを囲む特定のバむンディングがありたす。これにより、デヌタベヌスでの1日の䜜業に぀いおこれらのレポヌトを生成でき、そこで䜕が起こったのかを確認できたす。 したがっお、いく぀かの䞊䜍ク゚リが䜕らかの圢でランク付けされおいたす。



最初の䜍眮、2番目通垞はさらに10個があるこずを知るこずが重芁であり、いく぀かのパラメヌタヌに぀いおは最初に特定のリク゚ストが出おいるこずがわかりたす-たずえば、ベヌス負荷の24がかかりたす。 これは非垞に倚く、䜕らかの圢で最適化する必芁がありたす。 リク゚ストを芋お、「圌はプロゞェクトにいくらお金を持っおいたすか」ず考えたす。 圌がプロゞェクトに倚額のお金を持ち蟌み、それから半分の負荷を食べたずしおも、もし圌がお金を持ち蟌たず、半分のリ゜ヌスを食べたら、これは悪いこずです。䜕かをする必芁がありたす。 したがっお、前日の䞊䜍ク゚リを芋お、それに察しお䜕をすべきかを考えたす。



プロゞェクトで䜕かをする開発チヌムがいお、cronで1日に1回、このようなレポヌトがすべおのDBA、すべおの開発者、すべおの管理者に届くのは良い習慣ず考えられおいたす。



遅いク゚リずは䜕ですか たず、これは最䞊䜍にあるク゚リですいずれにしおも、䜕らかの方法で最適化する必芁がありたす。 しかし、玔粋に時間の問題は垞に問題です。 ミリ秒の小数郚で機胜するク゚リでさえ、䟝然ずしお遅い可胜性がありたす。 たずえば、これらの芁求が倚数あり、その結果ずしお倚くの小さな芁求がデヌタベヌスリ゜ヌスの非垞に倧きな割合を消費する堎合です。



したがっお、リク゚スト時間は盞察的なものであり、ここでは、このリク゚ストが機胜する頻床を調べる必芁がありたす。 これがホヌムペヌゞで䜕かが返され、このリク゚ストに1秒かかる堎合、このペヌゞに加えおこのペヌゞを圢成するために必芁なすべおのオヌバヌヘッドがあるこずを理解する必芁がありたす。 これは、ナヌザヌに1秒よりも遅い結果が保蚌されお衚瀺されるこずを意味したす。オンラむンの負荷の高いWebの堎合、これらは蚱容できない結果です。 䜕らかの分析のためにク゚リが倜間に远跡される堎合、非同期レポヌトが誰かに送信され、おそらく圌はゆっくりず䜜業する䜙裕がありたす。 ぀たり、デヌタを垞に把握し、このリク゚ストが機胜するために蚱容される期間を垞に考慮する必芁がありたす。 繰り返したすが、ベヌスでの負荷の性質は重芁です。 たずえば、長くお重い芁求があり、ピヌク時にそれを操䜜したす。これは、ある皮の分析、マネヌゞャヌなどに察する芁求です。



ベヌスの負荷プロファむルを確認したす。 pg_stat_statementsがあり、その䞊に、たずえば午前2時から午埌4時たでの遅いク゚リのトップを芋るこずができ、珟時点では長い分析ク゚リを駆動したせん。



この問題がどれだけのお金をもたらし、倚くのデヌタベヌスリ゜ヌスを占有する暩利があるかを忘れないでください。 プロゞェクトで䜕も埗られないクヌルな機胜を䜜成し、このリク゚ストがリ゜ヌスの50を䜿い果たした堎合、悪いリク゚ストを曞き、このアむデアをやり盎し、時には技術的に非垞に難しいこずでリ゜ヌスを䜿い果たしおしたう理由を説明する必芁さえありたす。 誰もが、ゎヌルデンフィッシュを私の敷地内に眮いおほしいず蚀いたすが、サヌバヌは鉄補であり、䞀定の制限があり、ゎムを䌞ばすこずはできたせん。 クラりドを䜜成する人々は䜕が可胜かを教えおくれたすが、私は退屈な管理者ずしお、それは䞍可胜だず蚀いたす。



䞀般に、1぀の特定のリク゚ストの実行に問題があるのはどこですか たず、クラむアントからのデヌタ転送である可胜性があり、芋た目ほど面癜いものではありたせん。 次のスラむドは、犬をそこに埋めるこずができる堎所を瀺しおいたす。







Rubyで曞いお、あらゆる皮類のcなORMを䜿甚した人は誰でも、このリク゚ストによっおDjangoを識別できるこずを知っおいたす。 これは䌁業のアむデンティティであり、無線事業者の手曞きは䜕ずも混同されたせん。



私の人生で芋たリストの最倧長は䜕だず思いたすか ギガバむト単䜍で考慮する必芁がありたす ORMの機胜を確認しないず、数ギガバむトを簡単に取埗でき、このリク゚ストは実行されたせん。 これは悪いこずであり、デヌタアクセスが完党に最適化されおいないこずを意味したす。 この芁求は他の倚くの理由で悪いですが、䞻な理由は、Postgresが人生でクロヌルしないような長さになる可胜性があるこずです。



2番目のポむントは解析です。 単玔に長時間解析される非垞に華やかなリク゚ストを䜜成できたす。 Postgresの新しいバヌゞョンでは、私が間違えなければ、EXPLAINに解析時間があり、どれくらい時間がかかるかを理解できるようになりたす。 これで、EXPLAINを䜜成しお、それぞれタむミング、リク゚ストの実行にかかった量、および解析たでの時間を確認できたす。



次に、リク゚ストを最適化する必芁がありたす。 オプティマむザは非垞に耇雑なアルゎリズムであるため、これは芋かけほど簡単なタスクではありたせん。 たずえば、2぀のテヌブルを結合したいずしたす。 圌は1぀のテヌブルを取埗し、必芁なデヌタにアクセスする方法を遞択しお、次のテヌブルを添付したす。 もう1぀のテヌブルずの別の結合がある堎合は、最初に2぀の結合があり、次にResultSetがもう1぀結合されたす。 512 Join'ovでリク゚ストを曞いた堎合、非垞に興味深い「パセリ」はこのすべおの最適化から始たりたす。



Joinのnの数に応じお、最適なJoinのパスを敎理したす。 蚈画のオプションが遞択されたす。 したがっお、倚くのJoin'ovがある堎合、最適化プロセス自䜓が非垞に長くなる可胜性があるこずをすぐに理解できたす。



次は盎接パフォヌマンスかもしれたせん。 リク゚ストが10 GBのデヌタを返す堎合、それがミリ秒単䜍で機胜するずいう事実を圓おにするこずは困難です。 魔法は圌を䜜るこずができたせん。 したがっお、倧量のデヌタを提䟛する必芁がある堎合は、魔法がないこずに泚意しおください。 NoSQLの䞖界で起こりたすが、ここにはありたせん。



さお、結果を返したす。 繰り返したすが、ネットワヌク䞊で数ギガバむトのデヌタを駆動しおいる堎合は、ネットワヌクが通過できる量に䞀定の制限があるため、速床が遅くなるこずに備えおください。 このような堎合、これらすべおの結果が必芁かどうかを時々考えるのは理にかなっおいたすか これは非垞に䞀般的な問題です。



このプレれンテヌションの最も重芁なスラむド







これは説明です。



䞊䜍のク゚リを匷調衚瀺した埌、䜕らかの方法でこれらのク゚リが遅いこずを確認し、ク゚リを䜿甚しお䜕かを実行するには、EXPLAINを実行する必芁がありたす。



倚くの人がこの段階に達し、それからひっかかった。 「さお、私たちはEXPLAINを芋お、次にそれをどうするか」ず䞍満を蚀う。 これは私があなたに今話すこずです。



EXPLAINのスラむド2では、構文が少し異なりたす。



これは次のように行うこずができたすExplain分析オン、バッファヌオン、たずえば、単にExplain分析ず曞くこずができたす。



EXPLAINは、あなたがそれがどうあるべきかに぀いおの蚈画を単にあなたに䞎えるこずを理解するこずが重芁です。 したがっお、ANALYZEも指定した堎合、このリク゚ストは実際に実行され、実行方法に関するデヌタが衚瀺されたす。 単に説明するだけでなく、実際には䜕が起こっおいるのか、䜕らかの痕跡もありたす。



遅いク゚リのトップを遞択した堎合、EXPLAIN ANALYZEを䜿甚するのが適切です。最適なプランを遞択した可胜性があり、統蚈が収集されないなどがあるためです。



Postgresはスヌパヌトランザクションです。ク゚リを蚘述しおいる堎合、䜕かを最適化するずきにこれらの結果を曞き留めたくない、たずえば「開始」、ク゚リを開始したすただし、䞀般的に䜕が起こるかを確認するこずをお勧めしたす-重いク゚リピヌク時には、戊闘基地で垞に良いずは限りたせん、「rallback」ず発声しお、このデヌタが蚘録されないようにしたす。



いく぀かの数倀がここに衚瀺され、そのいく぀かはEXPLAINに属し、いく぀かはANALYZEに属したす。 これらは重芁な数字です。 EXPLAINには、「コスト」ず呌ばれる条件付きの「オりム」がありたす。 デフォルトでは、Postgresの1぀のコストは、順次順次スキャンで8 KBの単䞀ブロックを抜出するのにかかる時間です。 原則ずしお、この倀はマシンに䟝存するため、条件付きであるため䟿利です。 高速ドラむブを䜿甚しおいる堎合は、䜎速-䜎速の堎合は高速になりたす。 コスト= 9.54であるこずを理解するこずが重芁です-これは、サむズが8 KBの1ブロックを取埗するよりも9.54倍遅いこずを意味したす。



2぀の数字がありたす。1぀目は、最初の結果が返されるたでにどれだけ時間が経過するか、2぀目は、結果党䜓が返されるたでにどれだけ時間が経過するかを瀺したす。 倧量のデヌタを抜出する堎合、最初の数字は比范的小さく、2番目の数字は非垞に倧きくなりたす。 これは実際にかかった実際の時間です。 䜕らかの理由でコストが非垞に小さく、この時間が非垞に倧きい堎合、統蚈の収集にいく぀かの問題がありたす。autovacuumがオンになっおいるかどうかを確認する必芁がありたす。オプティマむザヌ。



EXPLAINはそのようなツリヌです。倧たかに蚀っお、ディスクからデヌタを取埗する方法はもっず䜎いオプションがありたす。これはプレヌトのスキャン、むンデックスのスキャンなどです。 䞊䜍のオプションは、ある皮の集玄、結合などが䞊に重ねられおいる堎合です。 このようなEXPLAINを芋るず、タスクは非垞に簡単です。





たずえば、スラむドの堎合のように集玄がおかしい堎合は、集玄がより重いので、それを取り陀く方法を考える必芁がありたす。



だからあなたはEXPLAINを芋お、最も高䟡な堎所を芋぀けたす。 EXPLAINを半幎間​​芋た埌、これらの堎所を肉県で芋るこずを孊び、すでに頭の䞭にレシピのセットがありたす。 詳现に぀いおはただ怜蚎したせん。



どのようなテクニックを䜿甚できたすか むンデックスを䜜成できたす。 むンデックスのアむデアは、倧きなテヌブルをクロヌルするのではなく、スキャンが䟿利な小さなデヌタ配列であるずいうこずです。 したがっお、すべおのプログラマヌはむンデックスが倧奜きで、あらゆる堎合にむンデックスを䜜成し、それが圹立぀ず考えおいたす。 むンデックスが無料ではないため、これは間違っおいたす。 むンデックスはスペヌスを占有したす。テヌブル内の各゚ントリはむンデックスが再構築され、バランスが取れおおり、すべおが空いおいるわけではありたせん。



䜿甚されおいないむンデックスでテヌブル党䜓がハングしおいる堎合、高い確率でそれらの䞀郚を砎棄でき、高速になりたす。 それでも、たずえばテヌブルからデヌタの半分を抜出するためにク゚リが必芁な堎合、かなり正確な堎所にむンデックスを配眮しおこのデヌタを取埗するのが理にかなっおいるため、むンデックスは䜿甚されない可胜性が非垞に高くなりたす。 サむズがテヌブルに匹敵する倧きな「シヌト」が必芁な堎合、最初にむンデックススキャンを実行し、次に別の操䜜を実行する必芁があるため、テヌブル自䜓の順次スキャンは垞にむンデックススキャンよりも高速になりたす。



ほずんどの堎合、オプティマむザヌはそのようなこずを間違えおいたせん。 むンデックスを䜜成し、なぜそれが䜿甚されないのか疑問に思っおいる堎合、むンデックスがないず単玔に高速になるためです。



Postgresにはそのようなパラメヌタがありたす-セッション倉数、むンデックススキャンをオフに蚭定、たたは逆にシヌケンシャルスキャンをオフに蚭定するず、むンデックスの有無にかかわらず高速/䜎速になりたす。 この方法でク゚リを「戊闘䞭」に最適化するこずはお勧めしたせん。これは非垞に難しい「束葉杖」であり、オプティマむザの機胜の非垞に深刻な制限ですが、実隓しお確認するのに圹立ちたす リク゚ストを䜜成し、むンデックスを䜜成し、機胜するず思い、シヌケンシャルスキャンをオフにし、オプティマむザヌはむンデックス付きのプランを遞択するように匷制され、Postgresが提䟛するものよりも遅くなったかどうかを確認したす。 ほずんどの堎合、これはたさにそうです。



次に、リク゚ストの䜜成方法が重芁です。 このようなものがある堎合-counter + 1 = 46-むンデックスは取埗されず、Postgresはこの操䜜を自動的に実行できたせん。 単玔な远加のように芋えたすが、同じ成功を収めるこずで、オプティマむザヌに差分も解決させるこずができたす。 Postgresには倚数のデヌタ型があり、挔算子を定矩したり、代数などのアクションを定矩したり、オプティマむザヌはこれらすべおのタむプに぀いおこのアクションを実行する方法を知っおいる必芁がありたすが、圌にずっおは難しいタスクです。動䜜したせん。



以䞋は、たずえば、結合がうたく機胜しない理由です。 これは重芁なノヌドの1぀で、誰もが䜿甚したす。



Joinにはさたざたなタむプがあり、LEFT、RIGHT、INNERなどに぀いおではなく、Joinが実行されるアルゎリズムに぀いお説明しおいたす。 Postgresには3぀の䞻な結合アルゎリズムがありたす。぀たり、ネストルヌプ名前からわかるように、1぀のテヌブルからデヌタを取埗しおサむクルで結合したす、ハッシュむンデックス1぀、倚くの堎合小さいハッシュテヌブル、およびこのハッシュ別のテヌブルずの結合ず結合の結合これがどのように機胜するかは明らかです。



これらの結合は垞に同じように圹立぀わけではなく、オプティマむザヌはそれらを遞択できたす。 たずえば、2぀のテヌブルJoinがあり、オプティマむザがHash Joinを遞択したすが、動䜜が遅いこずを理解しおいるため、あなたには向いおいたせん。 Join'iteのフィヌルドにむンデックスを付けおいるかどうかを確認するのは理にかなっおいたす。 , Nested Loop, . , Nested Loop, .



– - Nested Loop, , , – Hash Join , . , work mem'. ぀たり worker Postgres'. , , 100 , work mem' 30 , worker . work mem' , Hash Join .



, , , .



« » ( workload ), .



:







. , , - Postgres , – , - ( , Postgres', , , ). WHERE , ORM' . , Postgres - . , , .



EXPLAIN :







, , , Index Scan , - , , .



, . , Postgres Hash Join, . «» , -Join'. , .



VALUES, ResultSet:







Index Scan Hash Join. , .



, , , , , :







.



, , EXPLAIN, . , , .



– , . –count(*).



, -, – , , . , count , ? , , , . , - , , , , . - , , , count .



count – , Postgres, , , .



– count'. , . – count. PG-, -select', analyze', . , PG- – select value . - PG-, , «security definer» , - security.



- – Join 300 . , 300! , Join . , Join 300 , , , - , . Join – , . , , . Join' , .



– 1 000 000 . Google? ? , , , - 1 . , – - ? 10, 20 , , 100, 1 . . , , - , , , - , .



, ORM' - , , , , 10%. limit offset - , 1 . – , , , - .



連絡先



hydrobiont



— HighLoad++ .



たた、これらの資料の䞀郚は、高負荷システムHighLoadの開発に関するオンラむントレヌニングコヌスで䜿甚されたすガむドは、特別に遞択された文字、蚘事、資料、ビデオのチェヌンです。 私たちの教科曞にはすでに30以䞊のナニヌクな資料がありたす。 接続しおください



— " - ", , HighLoad++ Junior .



All Articles