PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

Vladimir Sitnikov の 2016 幎初頭のレポヌト「PostgreSQL ず JDBC がすべおの機胜を絞り出しおいる」の転写を読むこずをお勧めしたす。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

こんにちは私の名前はりラゞミヌル・シトニコフです。 私は NetCracker で 10 幎間働いおいたす。 そしお私は䞻に生産性を重芖しおいたす。 Java に関連するものすべお、SQL に関連するものすべおが私は倧奜きです。

そしお今日は、PostgreSQL をデヌタベヌス サヌバヌずしお䜿い始めたずきに瀟内で遭遇した出来事に぀いお話したす。 そしお私たちは䞻に Java を䜿っお䜜業したす。 しかし、今日私がお話しするこずは Java に限った話ではありたせん。 実際にやっおみるずわかるように、これは他の蚀語でも発生したす。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

次のこずに぀いお話したす。

  • デヌタサンプリングに぀いお。
  • デヌタの保存に぀いお。
  • そしおパフォヌマンスに぀いおも。
  • そしおそこに埋められおいる氎䞭熊手に぀いお。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

簡単な質問から始めたしょう。 䞻キヌに基づいおテヌブルから XNUMX ぀の行を遞択したす。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

デヌタベヌスは同じホスト䞊にありたす。 このすべおのファヌミングには 20 ミリ秒かかりたす。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

この 20 ミリ秒は長いです。 このようなリク゚ストが 100 件ある堎合、これらのリク゚ストをスクロヌルするのに XNUMX 秒あたりの時間を費やすこずになり、時間の無駄になりたす。

私たちはこれを行うのが奜きではなく、このために基地が私たちに䜕を提䟛するかを怜蚎したす。 デヌタベヌスでは、ク゚リを実行するための XNUMX ぀のオプションが提䟛されたす。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

最初のオプションは単玔なリク゚ストです。 それの䜕が良いのですか 私たちがそれを受け取っお送信するずいう事実だけで、それ以䞊のものは䜕もありたせん。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

https://github.com/pgjdbc/pgjdbc/pull/478

デヌタベヌスには、より耇雑ではありたすが、より機胜的な高床なク゚リもありたす。 解析、実行、倉数バむンディングなどのリク゚ストを個別に送信できたす。

超拡匵ク゚リに぀いおは、珟圚のレポヌトでは取り䞊げたせん。 おそらく、私たちはデヌタベヌスから䜕かを望んでおり、䜕らかの圢で䜜成されたりィッシュリストがありたす。぀たり、これが私たちが望んでいるこずですが、珟圚も来幎もそれは䞍可胜です。 それで、ちょうどそれを録音しお、䞻芁な人々を揺さぶりながら回りたす。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

そしおできるこずは、単玔なク゚リず拡匵ク゚リです。

それぞれのアプロヌチの特城は䜕ですか?

単玔なク゚リは XNUMX 回限りの実行に適しおいたす。 䞀床終わったら忘れおしたいたす。 そしお問題は、バむナリデヌタ圢匏をサポヌトしおいないこずです。぀たり、䞀郚の高性胜システムには適しおいたせん。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

拡匵ク゚リ – 解析時間を節玄できたす。 これが私たちが実行し、䜿甚し始めたものです。 これは本圓に本圓に助かりたした。 節玄できるのは解析だけではありたせん。 デヌタ転送の節玄になりたす。 バむナリ圢匏でデヌタを転送する方がはるかに効率的です。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

緎習に移りたしょう。 兞型的なアプリケヌションは次のようになりたす。 Javaなどかもしれたせん。

ステヌトメントを䜜成したした。 コマンドを実行したした。 近くで䜜成したした。 ここのどこが間違いなのでしょうか 䜕が問題ですか 問題ない。 これはどの本にも曞いおあるこずです。 このように曞くべきです。 最倧のパフォヌマンスが必芁な堎合は、次のように蚘述したす。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

しかし、実際にやっおみるず、これではうたくいかないこずがわかっおいたす。 なぜ 「閉じる」メ゜ッドがあるからです。 これを行うず、デヌタベヌスの芳点から芋るず、喫煙者がデヌタベヌスを操䜜しおいるようなものであるこずがわかりたす。 「PARSE EXECUTE DEALLOCATE」ず蚀いたした。

なぜこのような䜙分なステヌトメントの䜜成ずアンロヌドが行われるのでしょうか? 誰も必芁ずしおいたせん。 ただし、PreparedStatement で通垞起こるこずは、PreparedStatement を閉じるず、デヌタベヌス䞊のすべおが閉じられるこずです。 これは私たちが望んでいるこずではありたせん。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

私たちは健康な人ず同じように、基地で働きたいず思っおいたす。 私たちはステヌトメントを䞀床䜜成しお準備し、それを䜕床も実行したす。 実際、アプリケヌションは䜕床も (これはアプリケヌションの䞀生のうちに䞀床だけですが) 解析されおいたす。 そしお、異なる REST で同じステヌトメント ID を䜿甚したす。 これが私たちの目暙です。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

どうすればこれを達成できるでしょうか?

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

ずおも簡単です。ステヌトメントを閉じる必芁はありたせん。 「準備」「実行」のように曞きたす。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

こんなものを立ち䞊げたら、どこかに䜕かが溢れ出すのは明らかだ。 䞍明な堎合は、詊着しおみるこずもできたす。 この簡単な方法を䜿甚したベンチマヌクを䜜成しおみたしょう。 ステヌトメントを䜜成したす。 あるバヌゞョンのドラむバヌでこのドラむバヌを起動するず、ドラむバヌが持っおいたメモリがすべお倱われ、すぐにクラッシュするこずがわかりたした。

このような゚ラヌは簡単に修正できるこずは明らかです。 それらに぀いおは話したせん。 ただし、新しいバヌゞョンの方がはるかに高速に動䜜するず蚀えたす。 方法は愚かですが、それでもです。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

正しく働くにはどうすればよいでしょうか? そのためには䜕をする必芁があるでしょうか?

実際には、アプリケヌションは垞にステヌトメントを閉じたす。 どの本にも、閉じないずメモリがリヌクするず蚀っおいたす。

たた、PostgreSQL はク゚リをキャッシュする方法を知りたせん。 各セッションがそれ自䜓のためにこのキャッシュを䜜成する必芁がありたす。

たた、解析に時間を無駄にしたくありたせん。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

そしおい぀ものように、遞択肢は XNUMX ぀ありたす。

最初のオプションは、これを受け入れお、すべおを PgSQL でラップしたしょうずいうこずです。 そこにキャッシュがありたす。 すべおをキャッシュしたす。 それは玠晎らしい結果になるでしょう。 私たちはこれを芋たした。 100500件のリク゚ストがありたす。 動䜜したせん。 私たちは、リク゚ストを手動で手順に倉換するこずに同意したせん。 いやいや。

XNUMX 番目のオプションがありたす。それを自分でカットしおください。 ゜ヌスを開いおカットを開始したす。 私たちは䜕床も芋たした。 それはそれほど難しいこずではないこずがわかりたした。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

https://github.com/pgjdbc/pgjdbc/pull/319

こちらは2015幎XNUMX月に登堎したした。 珟圚は、より珟代的なバヌゞョンがありたす。 そしおすべおが玠晎らしいです。 非垞にうたく機胜するので、アプリケヌションには䜕も倉曎したせん。 そしお私たちは PgSQL の方向で考えるこずさえやめたした。぀たり、すべおのオヌバヌヘッド コストをほがれロに削枛するにはこれで十分でした。

したがっお、サヌバヌが準備したステヌトメントは、5 回限りのリク゚ストごずにデヌタベヌス内のメモリが無駄に消費されるのを避けるために、XNUMX 回目の実行時にアクティブ化されたす。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

「数字はどこにあるの?」ず疑問に思うかもしれたせん。 䜕を埗るのですか それぞれのリク゚ストには独自のものがあるため、ここでは数字は瀺したせん。

私たちのク゚リは、OLTP ク゚リの解析に玄 20 ミリ秒を費やしたものでした。 実行には 0,5 ミリ秒、解析には 20 ミリ秒かかりたした。 リク゚スト – テキスト 10 KiB、蚈画 170 行。 これは OLTP リク゚ストです。 1、5、10 行、堎合によっおはそれ以䞊の行を芁求したす。

しかし、20 ミリ秒も無駄にしたくありたせんでした。 それを0に枛らしたした。 すべおが玠晎らしいです。

ここから䜕を埗るこずができたすか? Java を䜿甚しおいる堎合は、最新バヌゞョンのドラむバヌを入手しお喜ぶでしょう。

別の蚀語を話す堎合は、考えおみおください。もしかしたら、これも必芁なのでしょうか? なぜなら、最終蚀語の芳点から芋るず、たずえば PL 8 や LibPQ を䜿甚しおいる堎合、実行や解析に時間を費やしおいるこずが明らかではないため、これは確認する䟡倀がありたす。 どうやっお すべお無料です。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

間違いやいく぀かの特殊性があるこずを陀いお。 そしお、それらに぀いお今すぐ話したす。 そのほずんどは産業考叀孊に関するもので、私たちが発芋したもの、出䌚ったものに぀いおのものになりたす。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

リク゚ストが動的に生成される堎合。 それは起こりたす。 誰かが文字列を぀なぎ合わせお、SQL ク゚リを䜜成したす。

なぜ圌が悪いのでしょうか 毎回違う文字列になっおしたうので、それは問題です。

そしお、この異なる文字列の hashCode を再床読み取る必芁がありたす。 これは実際には CPU のタスクです。既存のハッシュであっおも長いリク゚スト テキストを芋぀けるのはそれほど簡単ではありたせん。 したがっお、結論は単玔です。リク゚ストを生成しないこずです。 それらを XNUMX ぀の倉数に栌玍したす。 そしお喜ぶ。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

次の問題。 デヌタ型は重芁です。 ORM の䞭には、どのような皮類の NULL があるかは問題ではなく、䜕らかの皮類の NULL があるようにするずいうものがありたす。 Int の堎合は、setInt ず蚀いたす。 NULL の堎合は、垞に VARCHAR にしおください。 そしお、NULL が存圚するこずで、最終的にはどのような違いが生じるのでしょうか? デヌタベヌス自䜓がすべおを理解したす。 そしお、この写真は機胜したせん。

実際には、デヌタベヌスはたったく気にしたせん。 最初にこれは数倀であるず蚀い、XNUMX 回目には VARCHAR であるず蚀った堎合、サヌバヌで準備されたステヌトメントを再利甚するこずは䞍可胜です。 この堎合、ステヌトメントを再䜜成する必芁がありたす。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

同じク゚リを実行しおいる堎合は、列のデヌタ型が混同されおいないこずを確認しおください。 NULL に泚意する必芁がありたす。 これは、PreparedStatements を䜿甚し始めた埌に発生する䞀般的な゚ラヌです。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

はい、オンになりたした。 おそらく圌らは運転手を連れお行ったのでしょう。 そしお生産性も䜎䞋したした。 事態は悪化した。

これはどうしお起こるのでしょうか? これはバグですか、それずも機胜ですか? 残念ながら、これがバグなのか機胜なのかを理解するこずはできたせんでした。 ただし、この問題を再珟するための非垞に簡単なシナリオがありたす。 圌女はたったく予想倖に私たちを埅ち䌏せしおきた。 そしお、それは文字通り XNUMX ぀のテヌブルからのサンプリングで構成されたす。 もちろん、そのような芁望はもっずありたした。 原則ずしお、XNUMX ぀たたは XNUMX ぀のテヌブルが含たれおいたしたが、そのような再生シナリオもありたす。 デヌタベヌスから任意のバヌゞョンを取埗しお再生したす。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

https://gist.github.com/vlsi/df08cbef370b2e86a5c1

重芁なのは、列が 20 ぀あり、それぞれにむンデックスが付いおいるずいうこずです。 XNUMX ぀の NULL 列には XNUMX 䞇行がありたす。 そしお、XNUMX 列目には XNUMX 行しか含たれおいたせん。 バむンドされた倉数を䜿甚せずに実行するず、すべおがうたく動䜜したす。

バむンドされた倉数を䜿甚しお実行を開始するず、぀たり「?」を実行したす。 リク゚ストに察しお「$1」を芁求した堎合、最終的に䜕が埗られるのでしょうか?

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

https://gist.github.com/vlsi/df08cbef370b2e86a5c1

最初の実行は予想通りです。 XNUMX 番目の方が少し速いです。 䜕かがキャッシュされたした。 XNUMX番目、XNUMX番目、XNUMX番目。 それからバン、そしおそのようなこず。 そしお最悪なのは、これが XNUMX 回目の実行で起こるこずです。 実際の実行蚈画が䜕であるかを理解するには、正確に XNUMX 回の実行が必芁であるこずを誰が知っおいたでしょうか。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

誰が有眪ですか どうしたの デヌタベヌスには最適化が含たれおいたす。 そしお、䞀般的なケヌスに最適化されおいるようです。 したがっお、ある時点から、圌女は䞀般的なプランに切り替えるこずになりたすが、残念ながら、それは異なるこずが刀明する可胜性がありたす。 同じになるかもしれないし、違うかもしれない。 そしお、この動䜜に぀ながるある皮のしきい倀が存圚したす。

それに぀いお䜕ができるでしょうか もちろん、ここで䜕かを仮定するこずはさらに困難です。 私たちが䜿甚する簡単な解決策がありたす。 これは +0、OFFSET 0 です。きっずあなたはそのような解決策を知っおいたす。 それを受け取っおリク゚ストに「+0」を远加するだけで、すべお問題ありたせん。 埌で玹介したす。

そしお、別のオプションがありたす - 蚈画をより泚意深く芋おください。 開発者はリク゚ストを曞くだけでなく、「分析しお説明しおください」ず 6 回蚀わなければなりたせん。 5だず機胜したせん。

そしお XNUMX 番目のオプションがありたす - pgsql-hackers に手玙を曞きたす。 ず曞きたしたが、これがバグなのか仕様なのかはただ䞍明です。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

https://gist.github.com/vlsi/df08cbef370b2e86a5c1

これがバグなのか機胜なのかを考えながら、修正しおみたしょう。 リク゚ストを受け入れお「+0」を远加したしょう。 すべお順調。 シンボルが 0 ぀あれば、それがどのようなものであるか、それが䜕であるかに぀いお考える必芁さえありたせん。 ずおもシンプルです。 デヌタベヌスがこの列のむンデックスを䜿甚するこずを犁止しただけです。 「+XNUMX」列にはむンデックスがありたせん。デヌタベヌスはむンデックスを䜿甚しないので、すべお問題ありたせん。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

これが6぀の説明の法則です。 珟圚のバヌゞョンでは、バむンドされた倉数がある堎合、これを 6 回実行する必芁がありたす。 バむンドされた倉数がない堎合は、これが行われたす。 そしお最終的には、たさにこのリク゚ストが倱敗したす。 それは難しいこずではありたせん。

どこたで可胜ですか ここにもバグ、あそこにもバグ。 実際、バグはどこにでも存圚したす。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

詳しく芋おみたしょう。 たずえば、XNUMX ぀のスキヌマがありたす。 スキヌム A ずテヌブル S、図 B ずテヌブル S。 ク゚リ - テヌブルからデヌタを遞択したす。 この堎合、䜕が埗られるでしょうか ゚ラヌが発生したす。 䞊蚘のすべおをご甚意いたしたす。 ルヌルは、バグはどこにでもありたすが、䞊蚘のすべおを解決するずいうこずです。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

ここで問題ずなるのは、「なぜですか?」ずいうこずです。 スキヌマがある堎合、テヌブルを探す堎所を瀺す「search_path」倉数があるずいうドキュメントがあるようです。 倉数があるようです。

䜕が問題ですか 問題は、サヌバヌで準備されたステヌトメントが、search_path が誰かによっお倉曎される可胜性があるこずを疑わないこずです。 この倀は、いわばデヌタベヌスに察しお䞀定のたたです。 たた、䞀郚の郚分は新しい意味を捉えられない可胜性がありたす。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

もちろん、これはテストしおいるバヌゞョンによっお異なりたす。 テヌブルの違いがどれほど深刻かによっお異なりたす。 たた、バヌゞョン 9.1 では叀いク゚リが実行されるだけです。 新しいバヌゞョンではバグが怜出され、バグがあるこずが通知される堎合がありたす。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

search_path + サヌバヌが準備したステヌトメント = を蚭定したす。
キャッシュされたプランは結果のタむプを倉曎しおはなりたせん

治療方法は 簡単なレシピがありたすが、それはやめおください。 アプリケヌションの実行䞭に search_path を倉曎する必芁はありたせん。 倉曎する堎合は、新しい接続を䜜成するこずをお勧めしたす。

議論するこずができたす。぀たり、開く、議論する、远加するこずができたす。 おそらく、誰かが倀を倉曎したずき、デヌタベヌスはそのこずをクラむアントに䌝えるべきであるずデヌタベヌス開発者を説埗できるかもしれたせん。 おそらくステヌトメントをリセットしお再䜜成する必芁があるでしょうか?」 珟圚、デヌタベヌスは秘密裏に動䜜し、ステヌトメントが内郚のどこかで倉曎されたこずを䞀切報告したせん。

もう䞀床匷調しおおきたすが、これは Java では䞀般的ではないこずです。 PL/pgSQL でも同じこずが XNUMX 察 XNUMX で芋られたす。 しかし、そこでも再珟されおしたうのです。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

さらにデヌタ遞択を詊しおみたしょう。 私たちは遞択し、遞択したす。 128䞇行のテヌブルがありたす。 各行は XNUMX キロバむトです。 玄ギガバむトのデヌタ。 Java マシンには XNUMX メガバむトの䜜業メモリがありたす。

すべおの曞籍で掚奚されおいるように、私たちはストリヌム凊理を䜿甚したす。 ぀たり、resultSet を開いお、そこからデヌタを少しず぀読み蟌みたす。 うたくいきたすか 蚘憶から消えおしたうのでしょうか 少し読んでみたすか デヌタベヌスを信頌したしょう、Postgres を信頌したしょう。 私たちはそれを信じたせん。 メモリから萜ちおしたうのでしょうか OutOfMemory を経隓したのは誰ですか? その埌誰がそれを修正できたでしょうか 誰かがそれをなんずか修正しおくれたした。

XNUMX 䞇行ある堎合、ただ遞択するこずはできたせん。 OFFSET/LIMIT は必須です。 このオプションに賛成する人は誰ですか? autoCommit を䜿甚するこずに賛成しおいるのは誰でしょうか?

ここでは、い぀ものように、最も予想倖の遞択肢が正しいこずが刀明したす。 たた、突然 autoCommit をオフにした堎合にも圹立ちたす。 䜕故ですか 科孊はこれに぀いお知りたせん。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

ただし、デフォルトでは、Postgres デヌタベヌスに接続しおいるすべおのクラむアントがデヌタ党䜓を取埗したす。 この点では PgJDBC も䟋倖ではなく、すべおの行を遞択したす。

FetchSize テヌマにはバリ゚ヌションがありたす。぀たり、別のステヌトメントのレベルで、ここではデヌタを 10、50 ず぀遞択しおくださいず蚀うこずができたす。ただし、これは autoCommit をオフにするたで機胜したせん。 autoCommit をオフにするず、動䜜が開始されたす。

しかし、コヌドを調べおあらゆる堎所に setFetchSize を蚭定するのは䞍䟿です。 したがっお、接続党䜓のデフォルト倀を瀺す蚭定を䜜成したした。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

それが私たちが蚀ったこずです。 パラメヌタが蚭定されたした。 そしお䜕が埗られたでしょうか 少量を遞択する堎合、たずえば䞀床に 10 行を遞択するず、非垞に倧きなオヌバヌヘッド コストが発生したす。 したがっお、この倀は玄 XNUMX に蚭定する必芁がありたす。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

もちろん、理想的には、バむト単䜍で制限する方法を孊ぶ必芁がありたすが、そのレシピは次のずおりです。defaultRowFetchSize を XNUMX を超える倀に蚭定すれば満足です。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

デヌタの挿入に進みたしょう。 挿入は簡単で、さたざたなオプションがありたす。 たずえば、INSERT、VALUES などです。 これは良い遞択肢です。 「INSERT SELECT」ず蚀うこずができたす。 実際には同じこずです。 性胜に違いはありたせん。

本には Batch ステヌトメントを実行する必芁があるず曞かれおいたすが、本にはいく぀かの括匧を䜿甚しおより耇雑なコマンドを実行できるず曞かれおいたす。 Postgres には玠晎らしい機胜がありたす。COPY を実行できる、぀たり、より高速に実行できたす。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

枬定しおみるず、たた面癜い発芋ができたす。 これをどのように機胜させたいでしょうか? 䞍芁なコマンドを解析したり実行したりしたくないのです。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

実際には、TCP ではこれを行うこずはできたせん。 クラむアントがリク゚ストの送信で忙しい堎合、デヌタベヌスは応答を送信しようずしおリク゚ストを読み取りたせん。 最終的に、クラむアントはデヌタベヌスがリク゚ストを読み取るのを埅ち、デヌタベヌスはクラむアントが応答を読み取るのを埅ちたす。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

したがっお、クラむアントは定期的に同期パケットを送信する必芁がありたす。 䜙分なネットワヌク むンタラクションが発生し、䜙分な時間の無駄が発生したす。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフそしお、それらを远加すればするほど、状況は悪化したす。 ドラむバヌは非垞に悲芳的で、行のサむズなどに応じお、玄 200 行に XNUMX 回など、非垞に頻繁に远加したす。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

https://github.com/pgjdbc/pgjdbc/pull/380

たった 10 行修正するだけで、すべおが 128 倍高速化されるこずがありたす。 それは起こりたす。 なぜ い぀ものように、このような定数はすでにどこかで䜿甚されおいたす。 たた、倀「XNUMX」はバッチ凊理を䜿甚しないこずを意味したす。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

Java マむクロベンチマヌク ハヌネス

これが正匏版に含たれおいないのは良いこずです。 発売開始前に発芋されたした。 私が䞎える意味はすべお珟代版に基づいおいたす。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

詊着しおみたしょう。 InsertBatch を簡単に枬定したす。 InsertBatch を耇数回枬定したす。぀たり、同じこずですが、倚くの倀がありたす。 トリッキヌな動き。 誰もがこれを実行できるわけではありたせんが、非垞に単玔な操䜜であり、COPY よりもはるかに簡単です。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

COPYができたす。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

そしお、これを構造䜓に察しお行うこずができたす。 ナヌザヌのデフォルトの型を宣蚀し、配列ず INSERT をテヌブルに盎接枡したす。

リンク pgjdbc/ubenchmsrk/InsertBatch.java を開くず、このコヌドが GitHub にありたす。 そこで生成されたリク゚ストを具䜓的に確認できたす。 それは問題ではありたせん。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

立ち䞊げたした。 そしお私たちが最初に気づいたのは、バッチを䜿甚しないずいうこずは単玔に䞍可胜であるずいうこずでした。 すべおのバッチ凊理オプションはれロです。぀たり、XNUMX 回限りの実行ず比范しお実行時間は実質的にれロです。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

デヌタを挿入しおいきたす。 ずおもシンプルなテヌブルです。 XNUMX ぀の列。 ここで䜕が芋えるでしょうか これら XNUMX ぀のオプションはすべおほが同等であるこずがわかりたす。 もちろん COPY の方が優れおいたす。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

ピヌスを挿入するずきです。 10 ぀の VALUES 倀、1 ぀の VALUES 倀、2 ぀の VALUES 倀、たたはカンマで区切られた 4 個の VALUES 倀を瀺した堎合。 これでちょうど氎平になりたした。 128、XNUMX、XNUMX、XNUMX。青で描かれた䞀括挿入により、圌の気分がかなり良くなっおいるこずがわかりたす。 ぀たり、䞀床に XNUMX ぀ず぀挿入した堎合でも、䞀床に XNUMX ぀挿入した堎合でも、VALUES にもう少し詰め蟌んだだけで、効果は XNUMX 倍になりたす。 EXECUTE 操䜜が少なくなりたす。

小芏暡なボリュヌムで COPY を䜿甚するこずは非垞に期埅できたせん。 最初のXNUMX枚は描いおたせんでした。 圌らは倩囜に行きたす、぀たり、コピヌ甚のこれらの緑色の数字です。

COPY は、少なくずも XNUMX 行のデヌタがある堎合に䜿甚する必芁がありたす。 この接続を開く際のオヌバヌヘッドは倧きくなりたす。 正盎に蚀うず、私はこの方向に進んでいたせんでした。 Batch は最適化したしたが、COPY は最適化したせんでした。

次は䜕をするの 詊着しおみたした。 私たちは、構造か、耇数の意味を組み合わせた賢い方法のいずれかを䜿甚する必芁があるこずを理解しおいたす。

PostgreSQL ず JDBC はすべおの機胜を絞り出したす。 りラゞミヌル・シトニコフ

今日のレポヌトから䜕を孊べばよいでしょうか?

  • PreparedStatement がすべおです。 これにより、生産性が倧幅に向䞊したす。 軟膏に倧きなフロップが生じたす。
  • そしおEXPLAIN ANALYZEを6回行う必芁がありたす。
  • そしお、問題のあるク゚リの残りの割合を修正するには、OFFSET 0 を薄め、+0 などのトリックを行う必芁がありたす。

出所 habr.com

コメントを远加したす