Uboreshaji mwingi wa maswali ya PostgreSQL. Kirill Borovikov (Tensor)

Ripoti inatoa baadhi ya mbinu zinazoruhusu fuatilia utendakazi wa hoja za SQL wakati kuna mamilioni yao kwa siku, na kuna mamia ya seva za PostgreSQL zinazofuatiliwa.

Ni suluhu gani za kiufundi huturuhusu kuchakata kwa ufanisi kiasi kama hicho cha habari, na je, hii inarahisisha vipi maisha ya msanidi programu wa kawaida?


Nani anavutiwa? uchambuzi wa matatizo maalum na mbinu mbalimbali za utoshelezaji Maswali ya SQL na kutatua shida za kawaida za DBA katika PostgreSQL - unaweza pia soma mfululizo wa makala juu ya mada hii.

Uboreshaji mwingi wa maswali ya PostgreSQL. Kirill Borovikov (Tensor)
Jina langu ni Kirill Borovikov, ninawakilisha Kampuni ya Tensor. Hasa, nina utaalam katika kufanya kazi na hifadhidata katika kampuni yetu.

Leo nitakuambia jinsi tunavyoboresha maswali, wakati huna haja ya "kuchagua" utendaji wa swali moja, lakini kutatua tatizo kwa wingi. Wakati kuna mamilioni ya maombi, na unahitaji kupata baadhi mbinu za ufumbuzi tatizo kubwa hili.

Kwa ujumla, Tensor kwa milioni ya wateja wetu ni VLSI ni maombi yetu: mtandao wa kijamii wa ushirika, ufumbuzi wa mawasiliano ya video, kwa mtiririko wa hati ya ndani na nje, mifumo ya uhasibu kwa uhasibu na maghala, ... Hiyo ni, "megacombine" kama hiyo ya usimamizi wa biashara jumuishi, ambayo kuna zaidi ya miradi 100 tofauti ya ndani. .

Ili kuhakikisha kuwa zote zinafanya kazi na kukua kama kawaida, tuna vituo 10 vya maendeleo nchini kote, vilivyo na zaidi ndani yake 1000 watengenezaji.

Tumekuwa tukifanya kazi na PostgreSQL tangu 2008 na tumekusanya kiasi kikubwa cha kile tunachochakata - data ya mteja, takwimu, uchambuzi, data kutoka kwa mifumo ya habari ya nje - zaidi ya 400TB. Kuna takriban seva 250 katika uzalishaji pekee, na kwa jumla kuna seva za hifadhidata 1000 ambazo tunafuatilia.

Uboreshaji mwingi wa maswali ya PostgreSQL. Kirill Borovikov (Tensor)

SQL ni lugha ya kutangaza. Unaelezea sio "jinsi" kitu kinapaswa kufanya kazi, lakini "nini" unataka kufikia. DBMS inajua vizuri jinsi ya kufanya JIUNGE - jinsi ya kuunganisha meza zako, ni masharti gani ya kuweka, nini kitapitia faharisi, ni nini ...

Baadhi ya DBMS zinakubali vidokezo: "Hapana, unganisha jedwali hizi mbili katika foleni kama hii," lakini PostgreSQL haiwezi kufanya hivi. Huu ndio msimamo makini wa wasanidi programu wakuu: "Tungependa kumaliza kiboreshaji hoja kuliko kuruhusu wasanidi programu kutumia aina fulani ya vidokezo."

Lakini, licha ya ukweli kwamba PostgreSQL hairuhusu "nje" kujidhibiti yenyewe, inaruhusu kikamilifu tazama kinachoendelea ndani yakeunapoendesha swali lako, na wapi ina matatizo.

Uboreshaji mwingi wa maswali ya PostgreSQL. Kirill Borovikov (Tensor)

Kwa ujumla, msanidi programu [kwa DBA] huwa na matatizo gani ya kawaida? β€œHapa tulitimiza ombi, na kila kitu ni polepole na sisi, kila kitu kinaning’inia, kuna kitu kinatokea... Shida fulani!”

Sababu ni karibu kila wakati sawa:

  • algorithm ya swala isiyofaa
    Msanidi programu: "Sasa ninampa meza 10 katika SQL kupitia JIUNGE ..." - na anatarajia kwamba masharti yake "yatafunguliwa" kwa njia ya muujiza na atapata kila kitu haraka. Lakini miujiza haifanyiki, na mfumo wowote wenye kutofautiana vile (meza 10 katika FROM moja) daima hutoa aina fulani ya makosa. [makala]
  • takwimu zisizo na maana
    Hoja hii ni muhimu sana kwa PostgreSQL, wakati "ulipomimina" mkusanyiko mkubwa wa data kwenye seva, tuma ombi, na "inafanya ngono" kompyuta yako ndogo. Kwa sababu jana kulikuwa na rekodi 10 ndani yake, na leo kuna milioni 10, lakini PostgreSQL bado haijafahamu hili, na tunahitaji kuiambia kuhusu hilo. [makala]
  • "plug" kwenye rasilimali
    Umesakinisha hifadhidata kubwa na iliyopakiwa sana kwenye seva dhaifu ambayo haina diski ya kutosha, kumbukumbu, au utendaji wa kichakataji. Na hiyo ndiyo yote ... Mahali fulani kuna dari ya utendaji juu ambayo huwezi tena kuruka.
  • kuzuia
    Hili ni jambo gumu, lakini linafaa zaidi kwa maswali anuwai ya kurekebisha (INGIZA, SASISHA, FUTA) - hii ni mada kubwa tofauti.

Kupata mpango

...Na kwa kila kitu kingine sisi haja ya mpango! Tunahitaji kuona kinachotokea ndani ya seva.

Uboreshaji mwingi wa maswali ya PostgreSQL. Kirill Borovikov (Tensor)

Mpango wa utekelezaji wa hoja kwa PostgreSQL ni mti wa algoriti ya utekelezaji wa hoja katika uwakilishi wa maandishi. Ni hasa algorithm ambayo, kama matokeo ya uchambuzi na mpangaji, ilionekana kuwa yenye ufanisi zaidi.

Kila nodi ya mti ni operesheni: kurejesha data kutoka kwa jedwali au faharasa, kuunda bitmap, kuunganisha majedwali mawili, kuunganisha, kukatiza, au kutojumuisha chaguo. Utekelezaji wa swali unahusisha kutembea kupitia nodi za mti huu.

Ili kupata mpango wa hoja, njia rahisi ni kutekeleza taarifa EXPLAIN. Ili kupata sifa zote halisi, ambayo ni, kutekeleza swali kwenye msingi - EXPLAIN (ANALYZE, BUFFERS) SELECT ....

Sehemu mbaya: unapoiendesha, hutokea "hapa na sasa", hivyo inafaa tu kwa utatuzi wa ndani. Ukichukua seva iliyopakiwa sana ambayo iko chini ya mtiririko mkali wa mabadiliko ya data, na unaona: "Lo! Hapa tunayo utekelezaji wa polepolesya ombi." Nusu saa, saa iliyopita - ulipokuwa ukiendesha na kupata ombi hili kutoka kwa kumbukumbu, ukilirudisha kwenye seva, mkusanyiko wako wote wa data na takwimu zilibadilika. Unaiendesha ili kurekebisha - na inaendesha haraka! Na huwezi kuelewa kwa nini, kwa nini ilikuwa polepole.

Uboreshaji mwingi wa maswali ya PostgreSQL. Kirill Borovikov (Tensor)

Ili kuelewa ni nini kilifanyika haswa wakati ombi lilitekelezwa kwenye seva, watu wenye akili waliandika moduli_ya_otomatiki. Inapatikana katika takriban usambazaji wote wa kawaida wa PostgreSQL, na inaweza kuamilishwa tu katika faili ya usanidi.

Ikitambua kuwa ombi fulani linaendelea kwa muda mrefu zaidi ya kikomo ulichoiambia, inafanya hivyo "Picha" ya mpango wa ombi hili na kuziandika pamoja kwenye logi.

Uboreshaji mwingi wa maswali ya PostgreSQL. Kirill Borovikov (Tensor)

Kila kitu kinaonekana kuwa sawa sasa, tunaenda kwenye logi na kuona huko ... [textcloth footcloth]. Lakini hatuwezi kusema lolote kuuhusu, zaidi ya ukweli kwamba ni mpango bora kwa sababu ilichukua 11ms kutekeleza.

Kila kitu kinaonekana kuwa sawa - lakini hakuna kilicho wazi ni nini kilitokea. Mbali na wakati wa jumla, hatuoni chochote. Kwa sababu kuangalia "mwana-kondoo" kama huyo wa maandishi wazi kwa ujumla sio kuonekana.

Lakini hata ikiwa sio wazi, hata ikiwa ni ngumu, kuna shida za kimsingi zaidi:

  • Nodi inaonyesha jumla ya rasilimali za subtree nzima chini yake. Hiyo ni, huwezi tu kujua ni muda gani uliotumika kwenye Uchanganuzi huu wa Index ikiwa kuna hali fulani ya kiota chini yake. Ni lazima tuangalie kwa uthabiti kuona kama kuna "watoto" na vigeu vya masharti, CTE ndani - na kuondoa haya yote "katika akili zetu".
  • Jambo la pili: wakati ambao umeonyeshwa kwenye nodi ni wakati wa utekelezaji wa nodi moja. Ikiwa node hii ilitekelezwa kutokana na, kwa mfano, kitanzi kupitia rekodi za meza mara kadhaa, basi idadi ya loops-mizunguko ya node hii-huongezeka katika mpango. Lakini wakati wa utekelezaji wa atomiki yenyewe unabaki sawa katika suala la mpango. Hiyo ni, ili kuelewa ni muda gani nodi hii ilifanywa kwa jumla, unahitaji kuzidisha kitu kimoja na kingine - tena, "kichwani mwako."

Katika hali kama hizi, elewa "Ni nani kiungo dhaifu zaidi?" karibu haiwezekani. Kwa hiyo, hata watengenezaji wenyewe huandika katika "mwongozo" huo "Kuelewa mpango ni sanaa ambayo lazima ijifunze, uzoefu ...".

Lakini tuna watengenezaji 1000, na huwezi kuwasilisha matumizi haya kwa kila mmoja wao. Mimi, wewe, anajua, lakini mtu huko hajui tena. Labda atajifunza, au labda la, lakini anahitaji kufanya kazi sasa - na angepata wapi uzoefu huu?

Panga taswira

Kwa hiyo, tuligundua kwamba ili kukabiliana na matatizo haya, tunahitaji taswira nzuri ya mpango. [makala]

Uboreshaji mwingi wa maswali ya PostgreSQL. Kirill Borovikov (Tensor)

Kwanza tulipitia "soko" - wacha tuangalie kwenye mtandao kuona ni nini kipo.

Lakini iliibuka kuwa kuna masuluhisho machache sana "ya moja kwa moja" ambayo yanakua zaidi au chini - halisi, moja tu: explain.depesz.com na Hubert Lubaczewski. Unapoingiza sehemu ya "milisho" uwakilishi wa maandishi ya mpango, inakuonyesha jedwali lililo na data iliyochanganuliwa:

  • wakati wa usindikaji wa nodi
  • jumla ya muda kwa subtree nzima
  • idadi ya rekodi ambazo zilirejeshwa ambazo zilitarajiwa kitakwimu
  • mwili wa nodi yenyewe

Huduma hii pia ina uwezo wa kushiriki kumbukumbu ya viungo. Ulitupa mpango wako hapo na kusema: "Halo, Vasya, hapa kuna kiunga, kuna kitu kibaya hapo."

Uboreshaji mwingi wa maswali ya PostgreSQL. Kirill Borovikov (Tensor)

Lakini pia kuna matatizo madogo.

Kwanza, kiasi kikubwa cha "copy-paste". Unachukua kipande cha logi, ukishikamishe huko, na tena, na tena.

Pili, hakuna uchambuzi wa kiasi cha data iliyosomwa - vibafa sawa na utoaji EXPLAIN (ANALYZE, BUFFERS), hatuioni hapa. Hajui jinsi ya kuzitenganisha, kuzielewa na kufanya kazi nazo. Unaposoma data nyingi na kugundua kuwa unaweza kuwa unatumia vibaya diski na kashe ya kumbukumbu, habari hii ni muhimu sana.

Jambo la tatu hasi ni maendeleo dhaifu sana ya mradi huu. Ahadi ni ndogo sana, ni vizuri ikiwa mara moja kila baada ya miezi sita, na nambari iko kwenye Perl.

Uboreshaji mwingi wa maswali ya PostgreSQL. Kirill Borovikov (Tensor)

Lakini hii yote ni "lyrics", tunaweza kuishi na hii kwa namna fulani, lakini kuna jambo moja ambalo lilituzuia sana kutoka kwa huduma hii. Haya ni makosa katika uchanganuzi wa Usemi wa Jedwali la Kawaida (CTE) na nodi mbalimbali zinazobadilika kama InitPlan/SubPlan.

Ikiwa unaamini picha hii, basi jumla ya muda wa utekelezaji wa kila nodi ya mtu binafsi ni kubwa kuliko muda wote wa utekelezaji wa ombi zima. Ni rahisi - wakati wa uzalishaji wa CTE hii haukutolewa kutoka kwa nodi ya Scan ya CTE. Kwa hiyo, hatujui tena jibu sahihi kwa muda gani uchunguzi wa CTE yenyewe ulichukua.

Uboreshaji mwingi wa maswali ya PostgreSQL. Kirill Borovikov (Tensor)

Kisha tukagundua kuwa ilikuwa wakati wa kuandika yetu - haraka! Kila msanidi anasema: "Sasa tutaandika yetu, itakuwa rahisi sana!"

Tulichukua rundo la kawaida kwa huduma za wavuti: msingi kulingana na Node.js + Express, tulitumia Bootstrap na D3.js kwa michoro nzuri. Na matarajio yetu yalihesabiwa haki kabisa - tulipokea mfano wa kwanza katika wiki 2:

  • kichanganuzi cha mpango maalum
    Hiyo ni, sasa tunaweza kuchanganua mpango wowote kutoka kwa zile zinazotolewa na PostgreSQL.
  • uchambuzi sahihi wa nodi zenye nguvu - CTE Scan, InitPlan, SubPlan
  • uchambuzi wa usambazaji wa bafa - ambapo kurasa za data zinasomwa kutoka kwa kumbukumbu, wapi kutoka kwa cache ya ndani, wapi kutoka kwa diski
  • ilipata uwazi
    Ili sio "kuchimba" haya yote kwenye logi, lakini kuona "kiungo dhaifu" mara moja kwenye picha.

Uboreshaji mwingi wa maswali ya PostgreSQL. Kirill Borovikov (Tensor)

Tulipata kitu kama hiki, pamoja na kuangazia sintaksia. Lakini kwa kawaida watengenezaji wetu hawafanyi kazi tena na uwakilishi kamili wa mpango, lakini kwa mfupi zaidi. Baada ya yote, tayari tumechanganua namba zote na kuzitupa kushoto na kulia, na katikati tuliacha mstari wa kwanza tu, ni aina gani ya node ni: CTE Scan, kizazi cha CTE au Seq Scan kulingana na ishara fulani.

Huu ndio uwakilishi wa kifupi tunaouita template ya mpango.

Uboreshaji mwingi wa maswali ya PostgreSQL. Kirill Borovikov (Tensor)

Nini kingine itakuwa rahisi? Itakuwa rahisi kuona ni sehemu gani ya wakati wetu wote imetengwa kwa nodi gani - na "ishike" tu kando. jedwali la mdwara.

Tunaelekeza kwenye node na kuona - zinageuka kuwa Seq Scan ilichukua chini ya robo ya muda wote, na 3/4 iliyobaki ilichukuliwa na CTE Scan. Hofu! Hili ni dokezo dogo kuhusu "kiwango cha moto" cha CTE Scan ikiwa utazitumia kikamilifu katika hoja zako. Sio haraka sana - ni duni hata kwa skanning ya kawaida ya meza. [makala] [makala]

Lakini kwa kawaida michoro kama hiyo inavutia zaidi, ngumu zaidi, tunapoelekeza mara moja kwenye sehemu na kuona, kwa mfano, kwamba zaidi ya nusu ya wakati Seq Scan "ilikula". Zaidi ya hayo, kulikuwa na aina fulani ya Kichujio ndani, rekodi nyingi zilitupwa kulingana na hilo ... Unaweza kutupa moja kwa moja picha hii kwa msanidi programu na kusema: "Vasya, kila kitu ni mbaya hapa kwako! Tambua, angalia - kuna kitu kibaya!

Uboreshaji mwingi wa maswali ya PostgreSQL. Kirill Borovikov (Tensor)

Kwa kawaida, kulikuwa na "raki" fulani zilizohusika.

Jambo la kwanza tulilopata lilikuwa shida ya kuzunguka. Wakati wa kila node ya mtu binafsi katika mpango unaonyeshwa kwa usahihi wa 1 ΞΌs. Na wakati idadi ya mizunguko ya nodi inapozidi, kwa mfano, 1000 - baada ya utekelezaji PostgreSQL imegawanywa "ndani ya usahihi", basi wakati wa kuhesabu nyuma tunapata muda wa jumla "mahali fulani kati ya 0.95ms na 1.05ms". Hesabu inapoenda kwa sekunde ndogo, hiyo ni sawa, lakini ikiwa tayari ni sekunde [milimita], unapaswa kuzingatia maelezo haya wakati wa "kufungua" rasilimali kwenye nodi za mpango wa "nani alitumia kiasi gani".

Uboreshaji mwingi wa maswali ya PostgreSQL. Kirill Borovikov (Tensor)

Hoja ya pili, ngumu zaidi, ni usambazaji wa rasilimali (bafa hizo) kati ya nodi zenye nguvu. Hii ilitugharimu wiki 2 za kwanza za mfano pamoja na wiki zingine 4.

Ni rahisi sana kupata aina hii ya shida - tunafanya CTE na eti tunasoma kitu ndani yake. Kwa kweli, PostgreSQL ni "smart" na haitasoma chochote moja kwa moja hapo. Kisha tunachukua rekodi ya kwanza kutoka kwake, na kwa hiyo mia moja na ya kwanza kutoka kwa CTE sawa.

Uboreshaji mwingi wa maswali ya PostgreSQL. Kirill Borovikov (Tensor)

Tunaangalia mpango na kuelewa - inashangaza, tuna bafa 3 (kurasa za data) "zinazotumiwa" katika Seq Scan, 1 zaidi katika CTE Scan, na 2 zaidi katika CTE Scan ya pili. Hiyo ni, ikiwa tu muhtasari wa kila kitu, tutapata 6, lakini kutoka kwa kibao tunasoma 3 tu! CTE Scan haisomi chochote kutoka popote, lakini inafanya kazi moja kwa moja na kumbukumbu ya mchakato. Yaani kuna kitu hakiko sawa hapa!

Kwa kweli, inageuka kuwa hapa kuna kurasa zote 3 za data ambazo ziliombwa kutoka kwa Seq Scan, kwanza 1 iliuliza 1 CTE Scan, na kisha ya 2, na 2 zaidi ilisomewa kwake. Hiyo ni, jumla ya Kurasa 3 zilisomwa data, sio 6.

Uboreshaji mwingi wa maswali ya PostgreSQL. Kirill Borovikov (Tensor)

Na picha hii ilituongoza kuelewa kwamba utekelezaji wa mpango sio mti tena, lakini ni aina fulani ya grafu ya acyclic. Na tulipata mchoro kama huu, ili tuelewe "nini kilitoka wapi hapo kwanza." Hiyo ni, hapa tuliunda CTE kutoka pg_class, na tukaiuliza mara mbili, na karibu wakati wetu wote ulitumiwa kwenye tawi tulipouliza mara ya 2. Ni wazi kwamba kusoma ingizo la 101 ni ghali zaidi kuliko kusoma tu ingizo la 1 kutoka kwa kompyuta kibao.

Uboreshaji mwingi wa maswali ya PostgreSQL. Kirill Borovikov (Tensor)

Tulishusha pumzi kwa muda. Walisema: β€œSasa, Neo, unajua kung fu! Sasa matumizi yetu yapo kwenye skrini yako. Sasa unaweza kuitumia." [makala]

Uimarishaji wa logi

Watengenezaji wetu 1000 walipumua kwa raha. Lakini tulielewa kuwa tuna mamia tu ya seva za "kupambana", na "nakala-kubandika" hii yote kutoka kwa watengenezaji sio rahisi hata kidogo. Tuligundua kwamba tulipaswa kuikusanya wenyewe.

Uboreshaji mwingi wa maswali ya PostgreSQL. Kirill Borovikov (Tensor)

Kwa ujumla, kuna moduli ya kawaida ambayo inaweza kukusanya takwimu, hata hivyo, inahitaji pia kuanzishwa katika usanidi - hii. pg_stat_statements moduli. Lakini hakutufaa.

Kwanza, inapeana maswali sawa kwa kutumia mifumo tofauti ndani ya hifadhidata moja QueryIds tofauti. Hiyo ni, ikiwa unafanya kwanza SET search_path = '01'; SELECT * FROM user LIMIT 1;, halafu SET search_path = '02'; na ombi sawa, basi takwimu za moduli hii zitakuwa na rekodi tofauti, na sitaweza kukusanya takwimu za jumla hasa katika muktadha wa wasifu huu wa ombi, bila kuzingatia mipango.

Jambo la pili lililotuzuia kuitumia ni ukosefu wa mipango. Yaani hakuna mpango, kuna ombi lenyewe tu. Tunaona nini kilikuwa kinapungua, lakini hatuelewi kwa nini. Na hapa tunarudi kwa shida ya mkusanyiko wa data unaobadilika haraka.

Na wakati wa mwisho - ukosefu wa "facts". Hiyo ni, huwezi kushughulikia mfano maalum wa utekelezaji wa hoja - hakuna, kuna takwimu zilizojumlishwa tu. Ingawa inawezekana kufanya kazi na hii, ni ngumu sana.

Uboreshaji mwingi wa maswali ya PostgreSQL. Kirill Borovikov (Tensor)

Kwa hiyo, tuliamua kupigana na nakala-kuweka na kuanza kuandika mtoza.

Mtoza huunganisha kupitia SSH, huanzisha muunganisho salama kwa seva na hifadhidata kwa kutumia cheti, na tail -F "inashikamana" nayo kwenye faili ya kumbukumbu. Hivyo katika kikao hiki tunapata "kioo" kamili cha faili nzima ya logi, ambayo seva hutoa. Mzigo kwenye seva yenyewe ni mdogo, kwa sababu hatuchanganuzi chochote hapo, tunaakisi trafiki tu.

Kwa kuwa tayari tumeanza kuandika interface katika Node.js, tuliendelea kuandika mtoza ndani yake. Na teknolojia hii imejihalalisha, kwa sababu ni rahisi sana kutumia JavaScript kufanya kazi na data ya maandishi yenye muundo dhaifu, ambayo ni logi. Na miundombinu ya Node.js yenyewe kama jukwaa la nyuma hukuruhusu kufanya kazi kwa urahisi na kwa urahisi na miunganisho ya mtandao, na kwa kweli na mitiririko yoyote ya data.

Ipasavyo, "tunanyoosha" viunganisho viwili: ya kwanza "kusikiliza" logi yenyewe na kuipeleka kwetu, na ya pili kuuliza msingi mara kwa mara. "Lakini logi inaonyesha kuwa ishara iliyo na oid 123 imezuiwa," lakini hii haimaanishi chochote kwa msanidi programu, na itakuwa nzuri kuuliza hifadhidata, "OID = 123 ni nini?" Na kwa hivyo tunauliza mara kwa mara msingi kile ambacho bado hatujui kuhusu sisi wenyewe.

Uboreshaji mwingi wa maswali ya PostgreSQL. Kirill Borovikov (Tensor)

"Kuna jambo moja tu ambalo hukuzingatia, kuna aina ya nyuki wanaofanana na tembo!.." Tulianza kutengeneza mfumo huu tulipotaka kufuatilia seva 10. Muhimu zaidi katika ufahamu wetu, ambapo baadhi ya matatizo yalitokea ambayo yalikuwa magumu kushughulikia. Lakini katika robo ya kwanza, tulipokea mia kwa ufuatiliaji - kwa sababu mfumo ulifanya kazi, kila mtu alitaka, kila mtu alikuwa vizuri.

Yote hii inahitaji kuongezwa, mtiririko wa data ni mkubwa na unafanya kazi. Kwa kweli, kile tunachofuatilia, kile tunachoweza kukabiliana nacho, ndicho tunachotumia. Pia tunatumia PostgreSQL kama hifadhi ya data. Na hakuna kitu cha haraka "kumwaga" data ndani yake kuliko operator COPY Bado.

Lakini "kumwaga" data sio teknolojia yetu. Kwa sababu ikiwa una takriban maombi 50k kwa sekunde kwenye seva mia moja, basi hii itatoa 100-150GB ya kumbukumbu kwa siku. Kwa hivyo, tulilazimika "kukata" msingi kwa uangalifu.

Kwanza, tulifanya kugawa kwa siku, kwa sababu, kwa kiasi kikubwa, hakuna mtu anayevutiwa na uwiano kati ya siku. Ni tofauti gani uliyokuwa nayo jana, ikiwa usiku wa leo ulizindua toleo jipya la programu - na tayari takwimu mpya.

Pili, tulijifunza (tulilazimishwa) sana, haraka sana kuandika kwa kutumia COPY. Hiyo ni, sio tu COPYkwa sababu yeye ni mwepesi kuliko INSERT, na hata kwa kasi zaidi.

Uboreshaji mwingi wa maswali ya PostgreSQL. Kirill Borovikov (Tensor)

Jambo la tatu - ilibidi kuacha vichochezi, kwa mtiririko huo, na funguo za kigeni. Yaani hatuna uadilifu wa rejea hata kidogo. Kwa sababu ikiwa una jedwali ambalo lina jozi ya FK, na unasema katika muundo wa hifadhidata kwamba "hapa kuna rekodi ya kumbukumbu ambayo inarejelewa na FK, kwa mfano, kwa kikundi cha rekodi," basi unapoiingiza, PostgreSQL. haina chochote kilichobaki isipokuwa jinsi ya kuichukua na kuifanya kwa uaminifu SELECT 1 FROM master_fk1_table WHERE ... na kitambulisho ambacho unajaribu kuingiza - ili tu kuhakikisha kuwa rekodi hii iko hapo, ili "usivunje" Ufunguo huu wa Kigeni kwa uwekaji wako.

Badala ya rekodi moja kwenye jedwali lengwa na faharisi zake, tunapata faida iliyoongezwa ya kusoma kutoka kwa jedwali zote zinazorejelea. Lakini hatuitaji hii hata kidogo - kazi yetu ni kurekodi iwezekanavyo na haraka iwezekanavyo na mzigo mdogo. Kwa hivyo FK - chini!

Hatua inayofuata ni mkusanyiko na hashing. Hapo awali, tulizitekeleza kwenye hifadhidata - baada ya yote, ni rahisi mara moja, rekodi inapofika, ifanye katika aina fulani ya kompyuta kibao. "plus one" moja kwa moja kwenye kichochezi. Kweli, ni rahisi, lakini jambo lile lile baya - unaingiza rekodi moja, lakini unalazimika kusoma na kuandika kitu kingine kutoka kwa jedwali lingine. Zaidi ya hayo, sio tu kusoma na kuandika, pia unafanya kila wakati.

Sasa fikiria kuwa unayo jedwali ambalo unahesabu tu idadi ya maombi ambayo yamepitia mwenyeji maalum: +1, +1, +1, ..., +1. Na wewe, kwa kanuni, hauitaji hii - yote yanawezekana jumla katika kumbukumbu juu ya mtoza na kutuma kwa hifadhidata kwa kwenda moja +10.

Ndio, ikiwa kuna shida fulani, uadilifu wako wa kimantiki unaweza "kuanguka", lakini hii ni kesi isiyo ya kweli - kwa sababu unayo seva ya kawaida, ina betri kwenye mtawala, unayo logi ya ununuzi, logi kwenye mfumo wa faili ... Kwa ujumla, sio thamani yake. Hasara ya tija unayopata kutokana na vichochezi vya kuendesha/FK haifai gharama unayotumia.

Ni sawa na hashing. Ombi fulani linaruka kwako, unahesabu kitambulisho fulani kutoka kwake kwenye hifadhidata, uandike kwenye hifadhidata na kisha uwaambie kila mtu. Kila kitu ni sawa mpaka, wakati wa kurekodi, mtu wa pili anakuja kwako ambaye anataka kurekodi kitu kimoja - na unazuiwa, na hii tayari ni mbaya. Kwa hivyo, ikiwa unaweza kuhamisha kizazi cha vitambulisho kwa mteja (kuhusiana na hifadhidata), ni bora kufanya hivyo.

Ilikuwa kamili kwetu kutumia MD5 kutoka kwa maandishi - ombi, mpango, template, ... Tunaihesabu kwa upande wa mtoza, na "kumwaga" kitambulisho kilicho tayari kwenye hifadhidata. Urefu wa MD5 na ugawaji wa kila siku huturuhusu tusiwe na wasiwasi juu ya migongano inayowezekana.

Uboreshaji mwingi wa maswali ya PostgreSQL. Kirill Borovikov (Tensor)

Lakini ili kurekodi haya yote haraka, tulihitaji kurekebisha utaratibu wa kurekodi yenyewe.

Je, huwa unaandikaje data? Tuna aina fulani ya seti ya data, tunaigawanya katika majedwali kadhaa, na kisha KUNAKILI - kwanza hadi ya kwanza, kisha hadi ya pili, hadi ya tatu ... Haifai, kwa sababu tunaonekana kuandika mkondo mmoja wa data katika hatua tatu. mfululizo. Isiyopendeza. Je, inaweza kufanyika kwa kasi? Je!

Ili kufanya hivyo, inatosha tu kuoza mtiririko huu kwa sambamba na kila mmoja. Inatokea kwamba tuna makosa, maombi, templates, kuzuia, ... kuruka kwa nyuzi tofauti - na tunaandika yote kwa sambamba. Kutosha kwa hili weka chaneli ya NAKALA wazi kila wakati kwa kila jedwali lengwa la mtu binafsi.

Uboreshaji mwingi wa maswali ya PostgreSQL. Kirill Borovikov (Tensor)

Hiyo ni, kwa mtoza daima kuna mkondo, ambayo ninaweza kuandika data ninayohitaji. Lakini ili hifadhidata ione data hii, na mtu asishike kusubiri data hii iandikwe, NAKALA lazima iingizwe kwa vipindi fulani. Kwa sisi, kipindi cha ufanisi zaidi kilikuwa karibu 100ms - tunaifunga na mara moja kuifungua tena kwenye meza sawa. Na ikiwa hatuna mtiririko wa kutosha wakati wa kilele fulani, basi tunakusanya hadi kikomo fulani.

Zaidi ya hayo, tuligundua kuwa kwa wasifu wa mzigo kama huo, mkusanyiko wowote, wakati rekodi zinakusanywa katika vikundi, ni mbaya. Uovu wa classic ni INSERT ... VALUES na rekodi zaidi 1000. Kwa sababu wakati huo una kilele cha kuandika kwenye vyombo vya habari, na kila mtu mwingine anayejaribu kuandika kitu kwenye diski atasubiri.

Ili kuondoa hitilafu kama hizo, usijumuishe chochote, usihifadhi hata kidogo. Na ikiwa buffering kwenye diski hutokea (kwa bahati nzuri, API ya Mkondo katika Node.js inakuwezesha kujua) - kuahirisha uhusiano huu. Unapopokea tukio ambalo ni bure tena, liandikie kutoka kwenye foleni iliyokusanywa. Na wakati kuna shughuli nyingi, chukua inayofuata bila malipo kutoka kwenye bwawa na uiandike.

Kabla ya kuanzisha mbinu hii ya kurekodi data, tulikuwa na takriban 4K za kuandika, na kwa njia hii tulipunguza mzigo kwa mara 4. Sasa wamekua mara nyingine 6 kutokana na hifadhidata mpya zinazofuatiliwa - hadi 100MB/s. Na sasa tunahifadhi kumbukumbu kwa muda wa miezi 3 iliyopita kwa kiasi cha 10-15TB, tunatarajia kwamba katika miezi mitatu tu msanidi yeyote ataweza kutatua tatizo lolote.

Tunaelewa matatizo

Lakini tu kukusanya data hizi zote ni nzuri, muhimu, muhimu, lakini haitoshi - inahitaji kueleweka. Kwa sababu haya ni mamilioni ya mipango tofauti kwa siku.

Uboreshaji mwingi wa maswali ya PostgreSQL. Kirill Borovikov (Tensor)

Lakini mamilioni hayawezi kudhibitiwa, lazima kwanza tufanye "ndogo". Na, kwanza kabisa, unahitaji kuamua jinsi utakavyopanga jambo hili "ndogo".

Tumegundua mambo matatu muhimu:

  • nani alituma ombi hili
    Hiyo ni, kutoka kwa programu gani "ilifika": interface ya wavuti, backend, mfumo wa malipo au kitu kingine.
  • ambapo ilivyotokea
    Kwenye seva gani maalum? Kwa sababu ikiwa una seva kadhaa chini ya programu moja, na ghafla moja "huenda kijinga" (kwa sababu "diski imeoza", "kumbukumbu imevuja", shida nyingine), basi unahitaji kushughulikia seva haswa.
  • kama tatizo lilijidhihirisha kwa namna moja au nyingine

Ili kuelewa "nani" alitutumia ombi, tunatumia zana ya kawaida - kuweka tofauti ya kipindi: SET application_name = '{bl-host}:{bl-method}'; β€” tunatuma jina la mwenyeji wa mantiki ya biashara ambapo ombi linatoka, na jina la mbinu au programu iliyoianzisha.

Baada ya kupitisha "mmiliki" wa ombi, lazima itolewe kwa logi - kwa hili tunasanidi kutofautisha. log_line_prefix = ' %m [%p:%v] [%d] %r %a'. Kwa wale wanaopenda, labda angalia kwenye mwongozoyote yanamaanisha nini. Inageuka kuwa tunaona kwenye logi:

  • wakati
  • vitambulisho vya mchakato na shughuli
  • jina la hifadhidata
  • IP ya mtu aliyetuma ombi hili
  • na jina la mbinu

Uboreshaji mwingi wa maswali ya PostgreSQL. Kirill Borovikov (Tensor)

Kisha tukagundua kuwa haifurahishi sana kuangalia uunganisho wa ombi moja kati ya seva tofauti. Si mara nyingi unakuwa na hali ambapo programu moja hujikwaa kwa usawa hapa na pale. Lakini hata ikiwa ni sawa, angalia yoyote ya seva hizi.

Hivyo hapa ni kata "seva moja - siku moja" iligeuka kuwa ya kutosha kwetu kwa uchambuzi wowote.

Sehemu ya kwanza ya uchambuzi ni sawa "sampuli" - fomu iliyofupishwa ya uwasilishaji wa mpango, kufutwa kwa viashiria vyote vya nambari. Kata ya pili ni maombi au njia, na kata ya tatu ni node maalum ya mpango ambayo ilituletea matatizo.

Tulipohama kutoka kwa hali maalum hadi violezo, tulipata faida mbili mara moja:

  • kupunguzwa kwa idadi ya vitu kwa uchambuzi
    Tunapaswa kuchanganua tatizo si kwa maelfu ya maswali au mipango, lakini kwa violezo vingi.
  • ratiba
    Hiyo ni, kwa muhtasari wa "ukweli" ndani ya sehemu fulani, unaweza kuonyesha muonekano wao wakati wa mchana. Na hapa unaweza kuelewa kwamba ikiwa una aina fulani ya muundo unaotokea, kwa mfano, mara moja kwa saa, lakini inapaswa kutokea mara moja kwa siku, unapaswa kufikiri juu ya kile kilichoharibika - ni nani aliyesababisha na kwa nini, labda inapaswa kuwa hapa. haipaswi. Hii ni njia nyingine isiyo ya nambari, ya kuona tu, ya uchambuzi.

Uboreshaji mwingi wa maswali ya PostgreSQL. Kirill Borovikov (Tensor)

Njia zilizobaki zinategemea viashiria ambavyo tunatoa kutoka kwa mpango: ni mara ngapi muundo kama huo ulitokea, jumla na wakati wa wastani, ni data ngapi iliyosomwa kutoka kwa diski, na ni ngapi kutoka kwa kumbukumbu ...

Kwa sababu, kwa mfano, unakuja kwenye ukurasa wa uchambuzi kwa mwenyeji, angalia - kitu kinaanza kusoma sana kwenye diski. Diski kwenye seva haiwezi kuishughulikia - ni nani anayesoma kutoka kwayo?

Na unaweza kupanga kwa safu yoyote na kuamua ni nini utashughulika nacho hivi sasa - mzigo kwenye processor au diski, au jumla ya idadi ya maombi ... Tulipanga, tukaangalia zile "juu", tukarekebisha na ilizindua toleo jipya la programu.
[hotuba ya video]

Na mara moja unaweza kuona programu tofauti zinazokuja na kiolezo sawa kutoka kwa ombi kama SELECT * FROM users WHERE login = 'Vasya'. Mazingira ya mbele, mazingira ya nyuma, usindikaji... Na unashangaa kwa nini usindikaji ungesoma mtumiaji ikiwa hataingiliana naye.

Njia tofauti ni kuona mara moja kutoka kwa programu kile inafanya. Kwa mfano, sehemu ya mbele ni hii, hii, hii, na hii mara moja kwa saa (line ya matukio husaidia). Na swali linatokea mara moja: inaonekana kama sio kazi ya mbele kufanya kitu mara moja kwa saa ...

Uboreshaji mwingi wa maswali ya PostgreSQL. Kirill Borovikov (Tensor)

Baada ya muda, tuligundua kuwa hatuna mkusanyiko takwimu kwa nodi za mpango. Tulitenga kutoka kwa mipango tu nodi hizo ambazo hufanya kitu na data ya jedwali zenyewe (soma / andika kwa faharisi au la). Kwa kweli, kipengele kimoja tu kinaongezwa kuhusiana na picha ya awali - hii nodi ilituletea rekodi ngapi?, na ni ngapi zilitupwa (Safu Mlalo Zimeondolewa na Kichujio).

Huna index inayofaa kwenye sahani, unatoa ombi kwake, inaruka nyuma ya index, huanguka kwenye Seq Scan ... umechuja rekodi zote isipokuwa moja. Kwa nini unahitaji rekodi zilizochujwa za 100M kwa siku? Je, si bora kukunja faharasa?

Uboreshaji mwingi wa maswali ya PostgreSQL. Kirill Borovikov (Tensor)

Baada ya kuchambua nodi zote za mipango kwa nodi, tuligundua kuwa kuna miundo ya kawaida katika mipango ambayo inaweza kuonekana ya kutiliwa shaka. Na itakuwa nzuri kumwambia msanidi programu: "Rafiki, hapa unasoma kwanza kwa faharisi, kisha kupanga, na kisha kukatwa" - kama sheria, kuna rekodi moja.

Kila mtu ambaye aliandika maswali labda amekutana na muundo huu: "Nipe agizo la mwisho la Vasya, tarehe yake." Na ikiwa huna faharisi kwa tarehe, au hakuna tarehe katika faharisi uliyotumia, basi utasikia. hatua kwenye "rake" sawa kabisa.

Lakini tunajua kuwa hii ni "rake" - kwa nini usimwambie msanidi programu mara moja kile anachopaswa kufanya. Ipasavyo, wakati wa kufungua mpango sasa, msanidi wetu huona mara moja picha nzuri na vidokezo, ambapo humwambia mara moja: "Una shida hapa na pale, lakini zinatatuliwa hivi na hivi."

Matokeo yake, kiasi cha uzoefu ambacho kilihitajika kutatua matatizo mwanzoni na sasa kimeshuka kwa kiasi kikubwa. Hii ndio aina ya zana tuliyo nayo.

Uboreshaji mwingi wa maswali ya PostgreSQL. Kirill Borovikov (Tensor)

Chanzo: mapenzi.com

Kuongeza maoni