Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

Iminumungkahi kong basahin mo ang transcript ng ulat ni Vladimir Sitnikov sa unang bahagi ng 2016 na "PostgreSQL at JDBC ay pinipiga ang lahat ng juice"

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

Magandang hapon Ang pangalan ko ay Vladimir Sitnikov. Ako ay nagtatrabaho para sa NetCracker sa loob ng 10 taon. At karamihan sa pagiging produktibo ko. Lahat ng bagay na may kaugnayan sa Java, lahat ng bagay na may kaugnayan sa SQL ay ang gusto ko.

At ngayon ay magsasalita ako tungkol sa kung ano ang nakatagpo namin sa kumpanya noong nagsimula kaming gumamit ng PostgreSQL bilang isang database server. At karamihan ay nagtatrabaho kami sa Java. Ngunit ang sasabihin ko sa iyo ngayon ay hindi lamang tungkol sa Java. Gaya ng ipinakita ng kasanayan, nangyayari rin ito sa ibang mga wika.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

Mag-uusap tayo:

  • tungkol sa data sampling.
  • Tungkol sa pag-save ng data.
  • At tungkol din sa performance.
  • At tungkol sa mga rake sa ilalim ng tubig na nakabaon doon.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

Magsimula tayo sa isang simpleng tanong. Pumili kami ng isang hilera mula sa talahanayan batay sa pangunahing key.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

Ang database ay matatagpuan sa parehong host. At ang lahat ng pagsasaka na ito ay tumatagal ng 20 milliseconds.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

Ang mga 20 millisecond na ito ay marami. Kung mayroon kang 100 ganoong mga kahilingan, gumugugol ka ng oras bawat segundo sa pag-scroll sa mga kahilingang ito, ibig sabihin, nag-aaksaya kami ng oras.

Hindi namin gustong gawin ito at tingnan kung ano ang inaalok sa amin ng base para dito. Ang database ay nag-aalok sa amin ng dalawang pagpipilian para sa pagpapatupad ng mga query.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

Ang unang pagpipilian ay isang simpleng kahilingan. Ano ang maganda dito? Ang katotohanan na kinukuha namin ito at ipinadala, at wala nang iba pa.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

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

Ang database ay mayroon ding advanced na query, na mas nakakalito, ngunit mas gumagana. Maaari kang hiwalay na magpadala ng kahilingan para sa pag-parse, pagpapatupad, variable binding, atbp.

Ang sobrang pinalawig na query ay isang bagay na hindi namin saklawin sa kasalukuyang ulat. Kami, marahil, ay may gusto mula sa database at mayroong isang listahan ng nais na nabuo sa ilang anyo, ibig sabihin, ito ang gusto namin, ngunit ito ay imposible ngayon at sa susunod na taon. Kaya ni-record lang namin ito at iikot namin ang mga pangunahing tao.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

At ang magagawa natin ay simpleng query at extended query.

Ano ang espesyal sa bawat diskarte?

Ang isang simpleng query ay mabuti para sa isang beses na pagpapatupad. Sa sandaling tapos na at nakalimutan. At ang problema ay hindi nito sinusuportahan ang format ng binary data, ibig sabihin, hindi ito angkop para sa ilang mga system na may mataas na pagganap.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

Pinalawak na query – nagbibigay-daan sa iyong makatipid ng oras sa pag-parse. Ito ang ginawa namin at sinimulan naming gamitin. Talagang nakatulong ito sa amin. Mayroong hindi lamang pagtitipid sa pag-parse. May mga matitipid sa paglilipat ng data. Ang paglilipat ng data sa binary na format ay mas mahusay.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

Magpatuloy tayo sa pagsasanay. Ito ang hitsura ng isang tipikal na application. Maaaring ito ay Java, atbp.

Gumawa kami ng pahayag. Isinagawa ang utos. Nilikha malapit. Saan ang pagkakamali dito? Ano ang problema? Walang problema. Ito ang sinasabi sa lahat ng libro. Ganito dapat ang pagsulat. Kung gusto mo ng maximum na performance, sumulat ng ganito.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

Ngunit ipinakita ng pagsasanay na hindi ito gumagana. Bakit? Dahil mayroon tayong "malapit" na pamamaraan. At kapag ginawa namin ito, mula sa database point of view ay lumalabas na ito ay tulad ng isang naninigarilyo na nagtatrabaho sa isang database. Sinabi namin na "PARSE EXECUTE DEALLOCATE".

Bakit ang lahat ng ito ay dagdag na paglikha at pagbabawas ng mga pahayag? Walang nangangailangan sa kanila. Ngunit ang kadalasang nangyayari sa PreparedStatements ay kapag isinara natin ang mga ito, isinasara nila ang lahat sa database. Hindi ito ang gusto natin.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

Gusto namin, tulad ng mga malulusog na tao, na magtrabaho kasama ang base. Kinuha namin at inihanda ang aming pahayag nang isang beses, pagkatapos ay isinasagawa namin ito ng maraming beses. Sa katunayan, maraming beses - ito ay isang beses sa buong buhay ng mga aplikasyon - sila ay na-parse. At ginagamit namin ang parehong statement id sa iba't ibang REST. Ito ang aming layunin.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

Paano natin ito makakamit?

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

Napakasimple - hindi na kailangang isara ang mga pahayag. Isinulat namin ito tulad nito: "maghanda" "isagawa".

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

Kung maglulunsad kami ng ganito, malinaw na may aapaw sa isang lugar. Kung hindi ito malinaw, maaari mo itong subukan. Sumulat tayo ng isang benchmark na gumagamit ng simpleng pamamaraang ito. Gumawa ng pahayag. Inilunsad namin ito sa ilang bersyon ng driver at nalaman na mabilis itong nag-crash sa pagkawala ng lahat ng memorya na mayroon ito.

Malinaw na ang gayong mga pagkakamali ay madaling itama. Hindi ko na sila pag-uusapan. Ngunit sasabihin ko na ang bagong bersyon ay gumagana nang mas mabilis. Ang pamamaraan ay hangal, ngunit pa rin.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

Paano magtrabaho nang tama? Ano ang kailangan nating gawin para dito?

Sa katotohanan, ang mga application ay palaging nagsasara ng mga pahayag. Sa lahat ng libro na sinasabi nilang isara ito, kung hindi, ang memorya ay tumagas.

At hindi alam ng PostgreSQL kung paano mag-cache ng mga query. Kinakailangan na ang bawat session ay lumikha ng cache na ito para sa sarili nito.

At ayaw din naming mag-aksaya ng oras sa pag-parse.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

At gaya ng dati, mayroon kaming dalawang pagpipilian.

Ang unang opsyon ay kunin natin ito at sabihin na ibalot natin ang lahat sa PgSQL. May cache doon. Ini-cache nito ang lahat. Ito ay magiging mahusay. Nakita namin ito. Mayroon kaming 100500 na kahilingan. Hindi gumagana. Hindi kami sumasang-ayon na gawing mga pamamaraan nang manu-mano ang mga kahilingan. Hindi hindi.

Mayroon kaming pangalawang pagpipilian - kunin ito at i-cut ito sa aming sarili. Binuksan namin ang mga mapagkukunan at simulan ang pagputol. Nakita at nakita namin. Ito ay lumabas na ito ay hindi napakahirap gawin.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

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

Ito ay lumitaw noong Agosto 2015. Ngayon ay may mas modernong bersyon. At lahat ay mahusay. Gumagana ito nang mahusay na hindi namin binago ang anumang bagay sa application. At huminto pa kami sa pag-iisip sa direksyon ng PgSQL, ibig sabihin, sapat na ito para bawasan namin ang lahat ng overhead na gastos sa halos zero.

Alinsunod dito, ang mga pahayag na inihanda ng server ay isinaaktibo sa ika-5 na pagpapatupad upang maiwasan ang pag-aaksaya ng memorya sa database sa bawat isang beses na kahilingan.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

Maaari kang magtanong - nasaan ang mga numero? Ano ang nakukuha mo? At dito hindi ako magbibigay ng mga numero, dahil ang bawat kahilingan ay may kanya-kanyang sarili.

Ang aming mga query ay tulad na gumugol kami ng humigit-kumulang 20 millisecond sa pag-parse sa mga query sa OLTP. Mayroong 0,5 millisecond para sa pagpapatupad, 20 millisecond para sa pag-parse. Kahilingan – 10 KiB ng text, 170 linya ng plano. Ito ay isang kahilingan sa OLTP. Humihiling ito ng 1, 5, 10 linya, minsan higit pa.

Ngunit hindi namin nais na mag-aksaya ng 20 millisecond. Binawasan namin ito sa 0. Lahat ay mahusay.

Ano ang maaari mong alisin dito? Kung mayroon kang Java, pagkatapos ay kunin mo ang modernong bersyon ng driver at magalak.

Kung nagsasalita ka ng ibang wika, isipin mo - baka kailangan mo rin ito? Dahil mula sa punto ng view ng panghuling wika, halimbawa, kung ang PL 8 o mayroon kang LibPQ, kung gayon hindi halata sa iyo na gumugugol ka ng oras hindi sa pagpapatupad, sa pag-parse, at ito ay nagkakahalaga ng pagsuri. Paano? Lahat ay libre.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

Maliban na may mga pagkakamali at ilang mga kakaiba. At pag-uusapan natin sila ngayon. Karamihan sa mga ito ay tungkol sa pang-industriyang arkeolohiya, tungkol sa kung ano ang aming nahanap, kung ano ang aming nakita.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

Kung dynamic na nabuo ang kahilingan. Nangyayari ito. May isang taong pinagdikit ang mga string, na nagreresulta sa isang query sa SQL.

Bakit siya masama? Masama dahil sa bawat oras na napupunta kami sa ibang string.

At ang hashCode ng ibang string na ito ay kailangang basahin muli. Ito ay talagang isang gawain ng CPU - ang paghahanap ng mahabang teksto ng kahilingan sa kahit na isang umiiral na hash ay hindi napakadali. Samakatuwid, ang konklusyon ay simple - huwag bumuo ng mga kahilingan. Itabi ang mga ito sa isang variable. At magsaya.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

Susunod na problema. Ang mga uri ng data ay mahalaga. May mga ORM na nagsasabi na hindi mahalaga kung anong uri ng NULL ang mayroon, magkaroon ng ilang uri. Kung Int, pagkatapos ay sinasabi namin setInt. At kung NULL, hayaan itong palaging VARCHAR. At ano ang pagkakaiba nito sa huli kung ano ang NULL? Ang database mismo ay mauunawaan ang lahat. At ang larawang ito ay hindi gumagana.

Sa pagsasagawa, ang database ay walang pakialam sa lahat. Kung sinabi mo sa unang pagkakataon na ito ay isang numero, at sa pangalawang pagkakataon na sinabi mo na ito ay isang VARCHAR, kung gayon imposibleng muling gamitin ang mga pahayag na inihanda ng Server. At sa kasong ito, kailangan nating muling likhain ang ating pahayag.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

Kung ipapatupad mo ang parehong query, tiyaking hindi malito ang mga uri ng data sa iyong column. Kailangan mong mag-ingat para sa NULL. Ito ay isang karaniwang error na mayroon kami pagkatapos naming simulan ang paggamit ng PreparedStatements

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

Okay, naka-on. Baka kinuha nila yung driver. At bumaba ang pagiging produktibo. Ang mga bagay ay naging masama.

Paano ito nangyayari? Ito ba ay isang bug o isang tampok? Sa kasamaang palad, hindi posible na maunawaan kung ito ay isang bug o isang tampok. Ngunit mayroong isang napakasimpleng senaryo para sa muling paggawa ng problemang ito. Sa hindi inaasahang pagkakataon ay tinambangan niya kami. At ito ay binubuo ng literal na sampling mula sa isang talahanayan. Kami, siyempre, ay nagkaroon ng higit pang mga naturang kahilingan. Bilang isang patakaran, kasama nila ang dalawa o tatlong mga talahanayan, ngunit mayroong isang senaryo ng pag-playback. Kumuha ng anumang bersyon mula sa iyong database at i-play ito.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

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

Ang punto ay mayroon tayong dalawang column, na ang bawat isa ay naka-index. Mayroong isang milyong row sa isang NULL column. At ang pangalawang hanay ay naglalaman lamang ng 20 linya. Kapag nag-execute kami nang walang nakatali na mga variable, gumagana nang maayos ang lahat.

Kung magsisimula kaming magsagawa ng mga nakatali na variable, ibig sabihin, ipapatupad namin ang "?" o "$1" para sa aming kahilingan, ano ang makukuha namin?

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

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

Ang unang pagpapatupad ay tulad ng inaasahan. Ang pangalawa ay medyo mas mabilis. May na-cache. Pangatlo, pang-apat, panglima. Pagkatapos putok - at isang bagay tulad na. At ang pinakamasama ay nangyari ito sa ikaanim na pagpapatupad. Sino ang nakakaalam na kinakailangang gawin ang eksaktong anim na execution upang maunawaan kung ano ang aktwal na plano sa pagpapatupad?

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

Sino ang may kasalanan? Anong nangyari? Ang database ay naglalaman ng pag-optimize. At tila na-optimize ito para sa generic na kaso. At, nang naaayon, simula sa isang punto, lumipat siya sa isang generic na plano, na, sa kasamaang-palad, ay maaaring maging iba. Maaaring magkapareho ito, o maaaring magkaiba. At mayroong ilang uri ng halaga ng threshold na humahantong sa gawi na ito.

Ano ang maaari mong gawin tungkol dito? Dito, siyempre, mas mahirap mag-assume ng anuman. Mayroong isang simpleng solusyon na ginagamit namin. Ito ay +0, OFFSET 0. Tiyak na alam mo ang mga ganitong solusyon. Kinukuha lang namin ito at idinagdag ang "+0" sa kahilingan at maayos ang lahat. Ipapakita ko sayo mamaya.

At may isa pang pagpipilian - tingnan ang mga plano nang mas maingat. Ang developer ay hindi lamang dapat magsulat ng isang kahilingan, ngunit sabihin din ang "ipaliwanag ang pagsusuri" ng 6 na beses. Kung ito ay 5, hindi ito gagana.

At mayroong isang pangatlong pagpipilian - sumulat ng isang liham sa mga pgsql-hacker. Isinulat ko, gayunpaman, hindi pa malinaw kung ito ay isang bug o isang tampok.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

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

Habang iniisip natin kung ito ba ay isang bug o isang tampok, ayusin natin ito. Kunin natin ang aming kahilingan at idagdag ang "+0". Maayos ang lahat. Dalawang simbolo at hindi mo na kailangang isipin kung paano ito o kung ano ito. Napakasimple. Ipinagbawal lang namin ang database na gumamit ng index sa column na ito. Wala kaming index sa column na "+0" at iyon lang, hindi ginagamit ng database ang index, maayos ang lahat.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

Ito ang tuntunin ng 6 ipaliwanag. Ngayon sa mga kasalukuyang bersyon kailangan mong gawin ito ng 6 na beses kung mayroon kang mga nakatali na variable. Kung wala kang mga nakatali na variable, ito ang ginagawa namin. At sa huli ay tiyak na ang kahilingang ito ang nabigo. Ito ay hindi isang nakakalito na bagay.

Mukhang, magkano ang posible? Isang bug dito, isang bug doon. Sa totoo lang, ang bug ay nasa lahat ng dako.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

Tingnan natin nang maigi. Halimbawa, mayroon kaming dalawang schema. Scheme A na may table S at diagram B na may table S. Query – pumili ng data mula sa isang talahanayan. Ano ang makukuha natin sa kasong ito? Magkakaroon tayo ng pagkakamali. Magkakaroon tayo ng lahat ng nasa itaas. Ang panuntunan ay - ang isang bug ay nasa lahat ng dako, magkakaroon tayo ng lahat ng nasa itaas.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

Ngayon ang tanong ay: "Bakit?" Mukhang mayroong dokumentasyon na kung mayroon kaming schema, mayroong isang variable na "search_path" na nagsasabi sa amin kung saan hahanapin ang talahanayan. Mukhang may variable.

Ano ang problema? Ang problema ay hindi pinaghihinalaan ng mga pahayag na inihanda ng server na maaaring baguhin ng isang tao ang search_path. Ang halagang ito ay nananatiling pare-pareho para sa database. At ang ilang bahagi ay maaaring hindi makakuha ng mga bagong kahulugan.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

Siyempre, depende ito sa bersyon na iyong sinusubok. Depende sa kung gaano kaseryoso ang pagkakaiba ng iyong mga talahanayan. At ang bersyon 9.1 ay isasagawa lamang ang mga lumang query. Maaaring mahuli ng mga bagong bersyon ang bug at sabihin sa iyo na mayroon kang bug.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

Itakda ang search_path + mga pahayag na inihanda ng server =
hindi dapat baguhin ng naka-cache na plano ang uri ng resulta

Paano ito gamutin? Mayroong isang simpleng recipe - huwag gawin ito. Hindi na kailangang baguhin ang search_path habang tumatakbo ang application. Kung magbabago ka, mas mabuting gumawa ng bagong koneksyon.

Maaari mong talakayin, ibig sabihin, buksan, talakayin, idagdag. Siguro maaari nating kumbinsihin ang mga developer ng database na kapag may nagbago ng isang halaga, dapat sabihin ng database sa kliyente ang tungkol dito: "Tingnan, ang iyong halaga ay na-update dito. Baka kailangan mong i-reset ang mga pahayag at muling likhain ang mga ito?” Ngayon ang database ay kumikilos nang lihim at hindi nag-uulat sa anumang paraan na ang mga pahayag ay nagbago sa isang lugar sa loob.

At muli kong idiin - ito ay isang bagay na hindi pangkaraniwan para sa Java. Makikita natin ang parehong bagay sa PL/pgSQL one to one. Ngunit ito ay ipaparami doon.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

Subukan natin ang ilang higit pang pagpili ng data. Pumili at pumili tayo. Mayroon kaming isang mesa na may isang milyong mga hilera. Ang bawat linya ay isang kilobyte. Tinatayang isang gigabyte ng data. At mayroon kaming gumaganang memorya sa Java machine na 128 megabytes.

Kami, gaya ng inirerekomenda sa lahat ng aklat, ay gumagamit ng pagpoproseso ng stream. Iyon ay, binubuksan namin ang resultSet at binabasa ang data mula doon paunti-unti. Gagana ba ito? Mawawala ba ito sa alaala? Magbabasa ka ba ng kaunti? Magtiwala tayo sa database, magtiwala tayo sa Postgres. Hindi kami naniniwala. Mawawala ba tayo sa OutOFMemory? Sino ang nakaranas ng OutOfMemory? Sino ang nakapag-ayos nito pagkatapos nito? May nakapag-ayos.

Kung mayroon kang isang milyong mga hilera, hindi ka maaaring pumili at pumili. OFFSET/LIMIT ang kailangan. Sino ang para sa pagpipiliang ito? At sino ang pabor sa paglalaro ng autoCommit?

Dito, gaya ng dati, ang pinaka hindi inaasahang opsyon ay lumalabas na tama. At kung bigla mong i-off ang autoCommit, makakatulong ito. Bakit ganon? Walang alam ang Science tungkol dito.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

Ngunit bilang default, kinukuha ng lahat ng kliyenteng kumokonekta sa database ng Postgres ang buong data. Ang PgJDBC ay walang pagbubukod sa bagay na ito; pinipili nito ang lahat ng mga hilera.

Mayroong pagkakaiba-iba sa tema ng FetchSize, ibig sabihin, maaari mong sabihin sa antas ng isang hiwalay na pahayag na dito, mangyaring pumili ng data bago ang 10, 50. Ngunit hindi ito gagana hanggang sa i-off mo ang autoCommit. Naka-off ang autoCommit - nagsisimula itong gumana.

Ngunit ang pagdaan sa code at setting na setFetchSize kahit saan ay hindi maginhawa. Samakatuwid, gumawa kami ng setting na magsasabi ng default na halaga para sa buong koneksyon.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

Yan ang sabi namin. Ang parameter ay na-configure. At ano ang nakuha namin? Kung pipili kami ng maliliit na halaga, kung, halimbawa, pumili kami ng 10 row sa isang pagkakataon, kung gayon mayroon kaming napakalaking gastos sa overhead. Samakatuwid, ang halagang ito ay dapat itakda sa halos isang daan.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

Sa isip, siyempre, kailangan mo pa ring matutunan kung paano limitahan ito sa mga byte, ngunit ang recipe ay ito: itakda ang defaultRowFetchSize sa higit sa isang daan at maging masaya.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

Lumipat tayo sa pagpasok ng data. Ang pagpasok ay mas madali, mayroong iba't ibang mga pagpipilian. Halimbawa, INSERT, VALUES. Ito ay isang magandang opsyon. Maaari mong sabihin ang "INSERT SELECT". Sa pagsasagawa ito ay ang parehong bagay. Walang pagkakaiba sa pagganap.

Sinasabi ng mga aklat na kailangan mong magsagawa ng isang Batch na pahayag, ang mga aklat ay nagsasabi na maaari kang magsagawa ng mas kumplikadong mga utos na may maraming panaklong. At may magandang feature ang Postgres - maaari mong gawin ang COPY, ibig sabihin, gawin ito nang mas mabilis.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

Kung susukatin mo ito, makakagawa ka muli ng ilang kawili-wiling pagtuklas. Paano natin ito gustong gumana? Nais naming huwag mag-parse at hindi magsagawa ng mga hindi kinakailangang utos.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

Sa pagsasagawa, hindi kami pinapayagan ng TCP na gawin ito. Kung abala ang kliyente sa pagpapadala ng kahilingan, hindi binabasa ng database ang mga kahilingan sa mga pagtatangkang magpadala sa amin ng mga tugon. Ang resulta ay naghihintay ang kliyente para sa database na basahin ang kahilingan, at ang database ay naghihintay para sa kliyente na basahin ang tugon.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

At samakatuwid ang kliyente ay pinipilit na pana-panahong magpadala ng isang packet ng pag-synchronize. Mga karagdagang pakikipag-ugnayan sa network, labis na pag-aaksaya ng oras.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir SitnikovAt kapag mas idinagdag natin ang mga ito, mas lumalala ito. Ang driver ay medyo pessimistic at idinagdag ang mga ito nang madalas, halos isang beses bawat 200 linya, depende sa laki ng mga linya, atbp.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

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

Ito ay nangyayari na itatama mo lamang ang isang linya at ang lahat ay bibilis ng 10 beses. Nangyayari ito. Bakit? Gaya ng dati, ang isang pare-parehong tulad nito ay nagamit na sa isang lugar. At ang halagang "128" ay sinadya na huwag gumamit ng batching.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

Java microbenchmark harness

Buti na lang hindi ito kasama sa official version. Natuklasan bago magsimula ang paglabas. Ang lahat ng mga kahulugan na ibinibigay ko ay batay sa mga modernong bersyon.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

Subukan natin ito. Sinusukat namin ang InsertBatch na simple. Sinusukat namin ang InsertBatch nang maraming beses, ibig sabihin, ang parehong bagay, ngunit maraming mga halaga. Mapanlinlang na galaw. Hindi lahat ay kayang gawin ito, ngunit ito ay isang simpleng hakbang, mas madali kaysa COPY.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

Pwede kang mag COPY.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

At magagawa mo ito sa mga istruktura. Ipahayag ang uri ng default ng User, ipasa ang array at INSERT nang direkta sa talahanayan.

Kung bubuksan mo ang link: pgjdbc/ubenchmsrk/InsertBatch.java, ang code na ito ay nasa GitHub. Maaari mong partikular na makita kung anong mga kahilingan ang nabuo doon. Hindi mahalaga.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

Inilunsad namin. At ang unang bagay na napagtanto namin ay ang hindi paggamit ng batch ay imposible lamang. Ang lahat ng mga pagpipilian sa pag-batch ay zero, ibig sabihin, ang oras ng pagpapatupad ay halos zero kumpara sa isang beses na pagpapatupad.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

Nagpasok kami ng data. Ito ay isang napakasimpleng mesa. Tatlong column. At ano ang nakikita natin dito? Nakikita namin na ang lahat ng tatlong mga opsyon na ito ay halos maihahambing. At ang COPY ay, siyempre, mas mahusay.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

Ito ay kapag nagpasok kami ng mga piraso. Noong sinabi namin na isang value ng VALUES, dalawang value ng VALUES, tatlong value ng VALUES, o ipinahiwatig namin ang 10 sa mga ito na pinaghihiwalay ng kuwit. Ito ay pahalang na lamang ngayon. 1, 2, 4, 128. Makikita na ang Batch Insert, na iginuhit sa kulay asul, ay higit na nagpapagaan sa kanyang pakiramdam. Ibig sabihin, kapag nagpasok ka ng paisa-isa o kahit na nagpasok ka ng apat nang sabay-sabay, nagiging doble ang husay nito, dahil lang mas na-crammed namin ang VALUES. Mas kaunting EXECUTE operations.

Ang paggamit ng COPY sa maliliit na volume ay lubhang hindi kapani-paniwala. Hindi man lang ako nagdrawing sa unang dalawa. Pumunta sila sa langit, ibig sabihin, itong mga berdeng numero para sa COPY.

Dapat gamitin ang COPY kapag mayroon kang kahit isang daang row ng data. Malaki ang overhead ng pagbubukas ng koneksyon na ito. At, sa totoo lang, hindi ako naghukay sa direksyong ito. Na-optimize ko ang Batch, ngunit hindi COPY.

Anong susunod nating gagawin? Sinubukan namin ito. Naiintindihan namin na kailangan naming gumamit ng alinman sa mga istruktura o isang matalinong bacth na pinagsasama ang ilang mga kahulugan.

Ang PostgreSQL at JDBC ay pinipiga ang lahat ng juice. Vladimir Sitnikov

Ano ang dapat mong alisin sa ulat ngayong araw?

  • Ang PreparedStatement ay ang aming lahat. Nagbibigay ito ng maraming para sa pagiging produktibo. Ito ay gumagawa ng isang malaking kabiguan sa pamahid.
  • At kailangan mong gawin ang EXPLAIN ANALYZE ng 6 na beses.
  • At kailangan naming tunawin ang OFFSET 0, at mga trick tulad ng +0 upang maitama ang natitirang porsyento ng aming mga may problemang query.

Pinagmulan: www.habr.com

Magdagdag ng komento