Margfínstilling á PostgreSQL fyrirspurnum. Kirill Borovikov (tensor)

Í skýrslunni eru kynntar nokkrar aðferðir sem leyfa fylgjast með frammistöðu SQL fyrirspurna þegar þær eru milljónir á dag, og það eru hundruðir af vöktuðum PostgreSQL netþjónum.

Hvaða tæknilausnir gera okkur kleift að vinna úr slíku magni upplýsinga á skilvirkan hátt og hvernig auðveldar það líf venjulegs þróunaraðila?


Hver hefur áhuga? greiningu á sérstökum vandamálum og ýmsum hagræðingaraðferðum SQL fyrirspurnir og leysa dæmigerð DBA vandamál í PostgreSQL - þú getur líka lestu röð greina um þetta efni.

Margfínstilling á PostgreSQL fyrirspurnum. Kirill Borovikov (tensor)
Ég heiti Kirill Borovikov, ég er fulltrúi Tensor fyrirtæki. Nánar tiltekið sérhæfi ég mig í að vinna með gagnagrunna í fyrirtækinu okkar.

Í dag skal ég segja þér hvernig við fínstillum fyrirspurnir, þegar þú þarft ekki að „tína í sundur“ frammistöðu einnar fyrirspurnar, heldur leysa vandamálið í massavís. Þegar það eru milljónir beiðna og þú þarft að finna nokkrar aðferðir til lausnar þetta stóra vandamál.

Almennt séð er Tensor fyrir milljón viðskiptavina okkar VLSI er umsókn okkar: félagslegt net fyrirtækja, lausnir fyrir myndbandssamskipti, fyrir innra og ytra skjalaflæði, bókhaldskerfi fyrir bókhald og vöruhús,... Það er svona „mega-samsetning“ fyrir samþætta viðskiptastjórnun, þar sem það eru meira en 100 mismunandi innri verkefni.

Til að tryggja að þau starfi og þróist öll eðlilega erum við með 10 þróunarsetur um allt land, með fleiri í þeim 1000 verktaki.

Við höfum unnið með PostgreSQL síðan 2008 og höfum safnað miklu magni af því sem við vinnum - viðskiptavinagögn, tölfræði, greiningar, gögn frá ytri upplýsingakerfum - meira en 400TB. Aðeins eru um 250 netþjónar í framleiðslu og alls eru um 1000 gagnagrunnsþjónar sem við fylgjumst með.

Margfínstilling á PostgreSQL fyrirspurnum. Kirill Borovikov (tensor)

SQL er yfirlýsingamál. Þú lýsir ekki „hvernig“ eitthvað ætti að virka heldur „hverju“ þú vilt ná. DBMS veit betur hvernig á að búa til JOIN - hvernig á að tengja töflurnar þínar, hvaða skilyrði á að setja, hvað fer í gegnum vísitöluna, hvað mun ekki...

Sumar DBMS samþykkja vísbendingar: „Nei, tengdu þessar tvær töflur í svona og svo biðröð,“ en PostgreSQL getur ekki gert þetta. Þetta er meðvituð staða leiðandi þróunaraðila: „Við viljum frekar klára fyrirspurnarfínstillinguna en að leyfa forriturum að nota einhvers konar vísbendingar.

En þrátt fyrir þá staðreynd að PostgreSQL leyfir ekki „ytri“ að stjórna sér, leyfir það fullkomlega sjá hvað er að gerast innra með honumþegar þú keyrir fyrirspurn þína og hvar það er í vandræðum.

Margfínstilling á PostgreSQL fyrirspurnum. Kirill Borovikov (tensor)

Almennt séð, hvaða klassísk vandamál kemur verktaki [til DBA] venjulega með? „Hér uppfylltum við beiðnina og allt gengur hægt hjá okkur, allt hangir, eitthvað er að gerast... Einhvers konar vandræði!“

Ástæðurnar eru næstum alltaf þær sömu:

  • óhagkvæmt fyrirspurnaralgrím
    Hönnuður: „Nú gef ég honum 10 töflur í SQL í gegnum JOIN...“ - og býst við því að aðstæður hans verði á kraftaverki í raun „óbundnar“ og hann muni fá allt fljótt. En kraftaverk gerast ekki og hvaða kerfi sem er með slíkan breytileika (10 töflur í einni FROM) gefur alltaf einhvers konar villu. [grein]
  • úrelt tölfræði
    Þetta atriði er mjög viðeigandi sérstaklega fyrir PostgreSQL, þegar þú „hellir“ stóru gagnasafni á netþjóninn, leggur fram beiðni og það „kynlíf“ spjaldtölvuna þína. Vegna þess að í gær voru 10 færslur í því og í dag eru þær 10 milljónir, en PostgreSQL er ekki enn meðvitað um þetta og við þurfum að segja það frá því. [grein]
  • „tengdu“ auðlindir
    Þú hefur sett upp stóran og mikið hlaðinn gagnagrunn á veikan miðlara sem hefur ekki nægjanlegan disk, minni eða afköst örgjörva. Og það er allt... Einhvers staðar er frammistöðuþak sem þú getur ekki lengur hoppað yfir.
  • lokun
    Þetta er erfiður punktur, en þær skipta mestu máli fyrir ýmsar breytingarfyrirspurnir (INSERT, UPDATE, DELETE) - þetta er sérstakt stórt efni.

Að fá áætlun

...Og fyrir allt annað sem við þarf áætlun! Við þurfum að sjá hvað er að gerast inni á þjóninum.

Margfínstilling á PostgreSQL fyrirspurnum. Kirill Borovikov (tensor)

Fyrirspurnarframkvæmdaráætlun fyrir PostgreSQL er tré af framkvæmdaralgrími fyrirspurnar í textaframsetningu. Það er einmitt reikniritið sem, vegna greiningar skipuleggjanda, reyndist vera áhrifaríkast.

Hver tréhnút er aðgerð: að sækja gögn úr töflu eða vísitölu, byggja bitamynd, sameina tvær töflur, sameina, skera eða útiloka val. Að framkvæma fyrirspurn felur í sér að ganga í gegnum hnúta þessa trés.

Til að fá fyrirspurnaáætlunina er auðveldasta leiðin að framkvæma yfirlýsinguna EXPLAIN. Til að fá alla raunverulega eiginleika, það er að framkvæma fyrirspurn á grunninn - EXPLAIN (ANALYZE, BUFFERS) SELECT ....

The slæmur hluti: þegar þú keyrir það gerist það "hér og nú", svo það er aðeins hentugur fyrir staðbundna kembiforrit. Ef þú tekur mjög hlaðinn netþjón sem er undir miklu flæði gagnabreytinga og þú sérð: „Ó! Hér höfum við hæga framkvæmdxia beiðni." Fyrir hálftíma, klukkutíma síðan - á meðan þú varst að keyra og fékk þessa beiðni úr annálunum, færði hana aftur á netþjóninn, breyttist allt gagnasafnið þitt og tölfræði. Þú keyrir það til að kemba - og það keyrir hratt! Og þú getur ekki skilið hvers vegna, hvers vegna var hægt.

Margfínstilling á PostgreSQL fyrirspurnum. Kirill Borovikov (tensor)

Til þess að skilja hvað gerðist nákvæmlega á því augnabliki þegar beiðnin var framkvæmd á þjóninum, skrifuðu klárir menn auto_explain mát. Það er til staðar í næstum öllum algengustu PostgreSQL dreifingum og er einfaldlega hægt að virkja það í stillingarskránni.

Ef það gerir sér grein fyrir því að einhver beiðni er lengur í gangi en mörkin sem þú sagðir henni við, gerir það það „skyndimynd“ af áætlun þessarar beiðni og skrifar þær saman í loggbókina.

Margfínstilling á PostgreSQL fyrirspurnum. Kirill Borovikov (tensor)

Allt virðist vera í lagi núna, við förum í stokkinn og sjáum þar... [texta fótklæði]. En við getum ekki sagt neitt um það, annað en þá staðreynd að þetta er frábær áætlun vegna þess að það tók 11 ms að framkvæma.

Allt virðist vera í lagi - en ekkert er ljóst hvað gerðist í raun og veru. Fyrir utan almennan tíma, sjáum við í raun ekki neitt. Vegna þess að það er almennt ekki sjónrænt að horfa á svona „lamb“ af einföldum texta.

En jafnvel þótt það sé ekki augljóst, jafnvel þótt það sé óþægilegt, þá eru grundvallarvandamál:

  • Hnúturinn gefur til kynna summa auðlinda alls undirtrésins undir honum. Það er að segja, þú getur ekki bara fundið út hversu miklum tíma var eytt í þessa tilteknu vísitöluskönnun ef það er eitthvað hreiðrað ástand undir henni. Við verðum að skoða kraftmikið til að sjá hvort það eru „börn“ og skilyrtar breytur, CTE inni – og draga allt þetta frá „í huga okkar“.
  • Annað atriði: tíminn sem er tilgreindur á hnútnum er framkvæmdartími eins hnúts. Ef þessi hnút var keyrður sem afleiðing af, til dæmis, lykkju í gegnum töfluskrár nokkrum sinnum, þá eykst fjöldi lykkjur - lotur þessa hnúts - í áætluninni. En atómaftökutíminn sjálfur er sá sami hvað varðar áætlun. Það er, til þess að skilja hversu lengi þessi hnút var framkvæmdur í heildina þarftu að margfalda eitt með öðru - aftur, "í höfðinu á þér."

Í slíkum aðstæðum skaltu skilja „Hver ​​er veikasti hlekkurinn? nánast ómögulegt. Þess vegna skrifa jafnvel verktaki sjálfir í „handbókinni“ það „Að skilja áætlun er list sem þarf að læra, upplifa...“.

En við erum með 1000 forritara og þú getur ekki miðlað þessari upplifun til hvers og eins. Ég, þú, hann veit, en einhver þarna veit það ekki lengur. Kannski lærir hann, eða kannski ekki, en hann þarf að vinna núna - og hvaðan fengi hann þessa reynslu?

Áætlunarsýn

Þess vegna áttum við okkur á að til að takast á við þessi vandamál þurfum við góð mynd af áætluninni. [grein]

Margfínstilling á PostgreSQL fyrirspurnum. Kirill Borovikov (tensor)

Við fórum fyrst „í gegnum markaðinn“ - við skulum skoða internetið til að sjá hvað er til.

En það kom í ljós að það eru mjög fáar tiltölulega „lifandi“ lausnir sem eru meira og minna að þróast - bókstaflega aðeins ein: explain.depesz.com eftir Hubert Lubaczewski Þegar þú slærð inn „straum“ reitinn textaframsetningu á áætluninni sýnir hún þér töflu með þáttuðu gögnunum:

  • eigin vinnslutíma hnútsins
  • heildartími fyrir allt undirtréð
  • fjöldi skráa sem voru sóttar sem búist var við tölfræðilega
  • hnúthlutinn sjálfur

Þessi þjónusta hefur einnig getu til að deila skjalasafni með tenglum. Þú kastaðir áætlun þinni þarna inn og sagðir: „Hey, Vasya, hér er hlekkur, það er eitthvað að þarna.“

Margfínstilling á PostgreSQL fyrirspurnum. Kirill Borovikov (tensor)

En það eru líka smá vandamál.

Í fyrsta lagi mikið magn af "copy-paste". Þú tekur bita af trjábolnum, stingur því þar inn og aftur og aftur.

Í öðru lagi, engin greining á magni lesins gagna — sömu biðminni og gefa út EXPLAIN (ANALYZE, BUFFERS), við sjáum það ekki hér. Hann veit einfaldlega ekki hvernig á að taka þau í sundur, skilja þau og vinna með þau. Þegar þú ert að lesa mikið af gögnum og áttar þig á því að þú gætir verið að úthluta disknum og minni skyndiminni ranglega, eru þessar upplýsingar mjög mikilvægar.

Þriðji neikvæði punkturinn er mjög veik þróun þessa verkefnis. Skuldbindingarnar eru mjög litlar, það er gott ef það er einu sinni á sex mánaða fresti og kóðinn er í Perl.

Margfínstilling á PostgreSQL fyrirspurnum. Kirill Borovikov (tensor)

En þetta er allt "textar", við gætum einhvern veginn lifað við þetta, en það er eitt sem vék okkur mjög frá þessari þjónustu. Þetta eru villur í greiningu á Common Table Expression (CTE) og ýmsum kraftmiklum hnútum eins og InitPlan/SubPlan.

Ef þú trúir þessari mynd, þá er heildarframkvæmdartími hvers einstaks hnút lengri en heildarframkvæmdartími allrar beiðninnar. Það er einfalt - kynslóðatími þessa CTE var ekki dreginn frá CTE Scan hnútnum. Þess vegna vitum við ekki lengur rétta svarið við því hversu langan tíma CTE skönnunin sjálf tók.

Margfínstilling á PostgreSQL fyrirspurnum. Kirill Borovikov (tensor)

Þá komumst við að því að það væri kominn tími til að skrifa okkar eigin - húrra! Sérhver verktaki segir: „Nú skrifum við okkar eigin, það verður mjög auðvelt!

Við tókum stafla sem er dæmigerður fyrir vefþjónustu: kjarna byggðan á Node.js + Express, notaði Bootstrap og D3.js fyrir fallegar skýringarmyndir. Og væntingar okkar voru fullkomlega réttlætanlegar - við fengum fyrstu frumgerðina eftir 2 vikur:

  • sérsniðinn áætlunarþáttari
    Það er, nú getum við flokkað hvaða áætlun sem er frá þeim sem eru búnar til af PostgreSQL.
  • rétt greining á kraftmiklum hnútum - CTE Scan, InitPlan, SubPlan
  • greining á dreifingu stuðpúða - þar sem gagnasíður eru lesnar úr minni, hvar úr staðbundnu skyndiminni, hvar af diski
  • fékk skýrleika
    Til að „grafa“ þetta ekki allt í logginu, heldur sjá „veikasta hlekkinn“ strax á myndinni.

Margfínstilling á PostgreSQL fyrirspurnum. Kirill Borovikov (tensor)

Við fengum eitthvað svona, með setningafræði auðkenningu innifalinn. En venjulega vinna verktaki okkar ekki lengur með heildarmynd af áætluninni, heldur með styttri. Enda erum við búin að flokka allar tölurnar og henda þeim til vinstri og hægri, og í miðjunni skildum við bara fyrstu línuna eftir, hvers konar hnútur það er: CTE Scan, CTE generation eða Seq Scan samkvæmt einhverju tákni.

Þetta er skammstafað framsetning sem við köllum áætlun sniðmát.

Margfínstilling á PostgreSQL fyrirspurnum. Kirill Borovikov (tensor)

Hvað annað væri þægilegt? Það væri þægilegt að sjá hvaða hluta af heildartíma okkar er úthlutað í hvaða hnút - og bara „stýra honum“ til hliðar kökurit.

Við bendum á hnútinn og sjáum - það kemur í ljós að Seq Scan tók minna en fjórðung af heildartímanum og 3/4 sem eftir voru voru teknir af CTE Scan. Hryllingur! Þetta er lítil athugasemd um „eldhraða“ CTE Scan ef þú notar þær virkan í fyrirspurnum þínum. Þeir eru ekki mjög hraðir - þeir eru lakari jafnvel en venjulega borðskönnun. [grein] [grein]

En venjulega eru slíkar skýringarmyndir áhugaverðari, flóknari, þegar við bendum strax á hluta og sjáum til dæmis að meira en helmingi tímans „át“ einhver Seq Scan. Þar að auki var einhvers konar sía inni, fullt af plötum var hent samkvæmt henni... Þú getur beint þessari mynd til framkvæmdaraðilans og sagt: "Vasya, allt er slæmt hér fyrir þig! Reiknaðu út, sjáðu - eitthvað er að!“

Margfínstilling á PostgreSQL fyrirspurnum. Kirill Borovikov (tensor)

Auðvitað voru nokkrar „hrífur“ í gangi.

Það fyrsta sem við komumst að var sléttunarvandamálið. Tími hvers einstaks hnúts í áætluninni er gefinn upp með 1 μs nákvæmni. Og þegar fjöldi hnútalota fer yfir, til dæmis, 1000 - eftir framkvæmd PostgreSQL skipt „innan nákvæmni“, þá fáum við heildartímann „einhvers staðar á milli 0.95ms og 1.05ms“ þegar við reiknum til baka. Þegar talningin fer í míkrósekúndur er það allt í lagi, en þegar það er nú þegar [milli]sekúndur, verður þú að taka tillit til þessara upplýsinga þegar þú „losar“ auðlindir við hnúta „hver neytti hversu mikið“ áætlunarinnar.

Margfínstilling á PostgreSQL fyrirspurnum. Kirill Borovikov (tensor)

Annað atriðið, flóknara, er dreifing auðlinda (þeirra biðminni) á milli kraftmikilla hnúta. Þetta kostaði okkur fyrstu 2 vikurnar af frumgerðinni auk 4 vikur í viðbót.

Það er frekar auðvelt að fá svona vandamál - við gerum CTE og lesum að sögn eitthvað í því. Reyndar er PostgreSQL „snjall“ og mun ekki lesa neitt beint þar. Síðan tökum við fyrsta metið úr henni og við það það hundrað og fyrsta frá sama CTE.

Margfínstilling á PostgreSQL fyrirspurnum. Kirill Borovikov (tensor)

Við lítum á áætlunina og skiljum - það er skrítið, við erum með 3 biðminni (gagnasíður) „neyddar“ í Seq Scan, 1 í viðbót í CTE Scan, og 2 í viðbót í annarri CTE Scan. Það er að segja, ef við tökum einfaldlega allt saman þá fáum við 6, en af ​​spjaldtölvunni lesum við bara 3! CTE Scan les ekki neitt hvaðan sem er, en vinnur beint með vinnsluminni. Það er að segja eitthvað er greinilega að hér!

Reyndar kemur í ljós að hér eru allar þessar 3 blaðsíður af gögnum sem beðið var um frá Seq Scan, fyrst 1 bað um 1. CTE skönnun og síðan 2. og 2 til viðbótar voru lesnar fyrir hann. Það er samtals 3 síður voru lesin gögn, ekki 6.

Margfínstilling á PostgreSQL fyrirspurnum. Kirill Borovikov (tensor)

Og þessi mynd leiddi okkur til þess skilnings að framkvæmd áætlunar er ekki lengur tré, heldur einfaldlega einhvers konar hringlaga línurit. Og við fengum skýringarmynd eins og þessa, svo að við skiljum "hvað kom frá í fyrsta lagi." Það er að segja, hér bjuggum við til CTE úr pg_class, og báðum um það tvisvar, og næstum allur tími okkar fór í útibúið þegar við báðum um það í 2. skiptið. Það er ljóst að lestur 101. færslunnar er mun dýrari en bara að lesa 1. færslu af spjaldtölvunni.

Margfínstilling á PostgreSQL fyrirspurnum. Kirill Borovikov (tensor)

Við önduðum frá okkur í smá stund. Þeir sögðu: „Nú, Neo, þú veist kung fu! Nú er upplifun okkar beint á skjánum þínum. Nú geturðu notað það." [grein]

Sameining logs

1000 verktaki okkar önduðu léttar. En við skildum að við höfum aðeins hundruð „bardaga“ netþjóna og allt þetta „copy-paste“ af hálfu þróunaraðila er alls ekki þægilegt. Við áttuðum okkur á því að við yrðum að safna því sjálf.

Margfínstilling á PostgreSQL fyrirspurnum. Kirill Borovikov (tensor)

Almennt séð er til stöðluð eining sem getur safnað tölfræði, en hún þarf líka að vera virkja í stillingunni - þetta pg_stat_statements mát. En hann hentaði okkur ekki.

Í fyrsta lagi úthlutar það sömu fyrirspurnum með mismunandi kerfum innan sama gagnagrunns mismunandi QueryIds. Það er að segja ef þú gerir það fyrst SET search_path = '01'; SELECT * FROM user LIMIT 1;og þá SET search_path = '02'; og sömu beiðni, þá mun tölfræði þessarar einingar hafa mismunandi skrár, og ég mun ekki geta safnað almennri tölfræði sérstaklega í samhengi við þetta beiðnisnið, án þess að taka tillit til kerfanna.

Annað atriðið sem kom í veg fyrir að við notum það er skortur á áætlunum. Það er, það er engin áætlun, það er aðeins beiðnin sjálf. Við sjáum hvað var að hægja á, en við skiljum ekki hvers vegna. Og hér snúum við aftur að vandamálinu með gagnasettum sem breytist hratt.

Og síðasta augnablikið - skortur á "staðreyndum". Það er, þú getur ekki tekið á tilteknu tilviki um framkvæmd fyrirspurnar - það er engin, það er aðeins samansafn tölfræði. Þó það sé hægt að vinna með þetta þá er þetta bara mjög erfitt.

Margfínstilling á PostgreSQL fyrirspurnum. Kirill Borovikov (tensor)

Þess vegna ákváðum við að berjast gegn copy-paste og byrjuðum að skrifa safnari.

Safnarinn tengist í gegnum SSH, kemur á öruggri tengingu við netþjóninn við gagnagrunninn með því að nota vottorð og tail -F „heldur“ við það í annálaskránni. Svo á þessu þingi við fáum fullkominn „spegil“ af allri annálaskránni, sem þjónninn býr til. Álagið á þjóninum sjálfum er í lágmarki, vegna þess að við greinum ekki neitt þar, við speglum bara umferðina.

Þar sem við vorum þegar byrjuð að skrifa viðmótið í Node.js héldum við áfram að skrifa safnarann ​​í það. Og þessi tækni hefur réttlætt sig, vegna þess að það er mjög þægilegt að nota JavaScript til að vinna með veikt sniðin textagögn, sem er loginn. Og Node.js innviðirnir sjálfir sem bakendir vettvangur gerir þér kleift að vinna með nettengingum á auðveldan og þægilegan hátt, og reyndar með hvaða gagnastrauma sem er.

Í samræmi við það „teygjum“ við tvær tengingar: sú fyrri til að „hlusta“ á annálinn sjálfan og taka hann til okkar og hinn til að spyrja stöðina reglulega. „En annálinn sýnir að merkið með oid 123 er læst,“ en þetta þýðir ekkert fyrir þróunaraðilann, og það væri gaman að spyrja gagnagrunninn: „Hvað er OID = 123 samt? Og því spyrjum við stöðina reglulega hvað við vitum ekki enn um okkur sjálf.

Margfínstilling á PostgreSQL fyrirspurnum. Kirill Borovikov (tensor)

„Það er bara eitt sem þú tókst ekki með í reikninginn, það er tegund af fílslíkum býflugum! ..“ Við byrjuðum að þróa þetta kerfi þegar við vildum fylgjast með 10 netþjónum. Það mikilvægasta í skilningi okkar, þar sem upp komu vandamál sem erfitt var að takast á við. En á fyrsta ársfjórðungi fengum við hundrað fyrir eftirlit - vegna þess að kerfið virkaði, allir vildu það, allir voru sáttir.

Allt þetta þarf að leggja saman, gagnaflæðið er mikið og virkt. Í raun er það sem við fylgjumst með, hvað við getum tekist á við, það sem við notum. Við notum einnig PostgreSQL sem gagnageymslu. Og ekkert er fljótlegra að „hella“ gögnum í það en rekstraraðilinn COPY Ekki enn.

En einfaldlega að „hella“ gögnum er í raun ekki okkar tækni. Vegna þess að ef þú ert með um það bil 50k beiðnir á sekúndu á hundrað netþjónum, þá mun þetta búa til 100-150GB af annálum á dag. Þess vegna þurftum við að „klippa“ grunninn vandlega.

Í fyrsta lagi gerðum við það skipting eftir degi, vegna þess að í stórum dráttum hefur enginn áhuga á fylgni milli daga. Hvaða máli skiptir það hvað þú hafðir í gær, ef þú settir í kvöld nýja útgáfu af forritinu - og þegar ný tölfræði.

Í öðru lagi lærðum við (vorum þvinguð) mjög, mjög fljótur að skrifa með því að nota COPY. Það er, ekki bara COPYþví hann er fljótari en INSERT, og jafnvel hraðar.

Margfínstilling á PostgreSQL fyrirspurnum. Kirill Borovikov (tensor)

Þriðja atriðið - ég varð að yfirgefa kveikjur, í sömu röð, og erlenda lykla. Það er, við höfum alls ekki tilvísunarheilindi. Vegna þess að ef þú ert með töflu sem hefur par af FKs og þú segir í gagnagrunnsbyggingunni að "hér er annálaskrá sem FK vísar til, til dæmis í hóp af færslum," þá þegar þú setur hana inn, PostgreSQL á ekkert eftir nema hvernig á að taka því og gera það heiðarlega SELECT 1 FROM master_fk1_table WHERE ... með auðkenninu sem þú ert að reyna að setja inn - bara til að athuga hvort þessi skrá sé til staðar þar, að þú "brjótir ekki af" þennan erlenda lykil með innsetningu þinni.

Í stað þess að eina skrá yfir marktöfluna og vísitölur hennar fáum við aukinn ávinning af því að lesa úr öllum töflunum sem hún vísar til. En við þurfum alls ekki á þessu að halda - verkefni okkar er að skrá eins mikið og mögulegt er og eins fljótt og hægt er með minnsta álagi. Svo FK - niður!

Næsti liður er samsöfnun og kjötkássa. Upphaflega settum við þær inn í gagnagrunninn - þegar allt kemur til alls er þægilegt að gera það strax, þegar skrá kemur, í einhvers konar spjaldtölvu "plús einn" beint í gikkinn. Jæja, það er þægilegt, en það sama slæma hluturinn - þú setur inn eina skrá, en neyðist til að lesa og skrifa eitthvað annað úr annarri töflu. Þar að auki, ekki aðeins lesið og skrifar, þú gerir það líka í hvert skipti.

Ímyndaðu þér nú að þú sért með töflu þar sem þú telur einfaldlega fjölda beiðna sem hafa farið í gegnum ákveðinn gestgjafa: +1, +1, +1, ..., +1. Og þú þarft þetta í grundvallaratriðum ekki - það er allt mögulegt summa í minni á safnara og senda í gagnagrunninn í einu lagi +10.

Já, ef upp koma einhver vandamál, gæti rökrétt heilindi þín „fallið í sundur“, en þetta er næstum óraunhæft tilfelli - vegna þess að þú ert með venjulegan netþjón, hann er með rafhlöðu í stjórnandanum, þú ert með viðskiptadagbók, log á skráarkerfi... Almennt séð er það ekki þess virði. Tapið á framleiðni sem þú færð með því að keyra triggers/FK er ekki þess virði kostnaðarins sem þú verður fyrir.

Það er eins með hass. Ákveðin beiðni flýgur til þín, þú reiknar út ákveðið auðkenni í gagnagrunninum, skrifar það í gagnagrunninn og segir það svo öllum. Allt er í lagi þar til við upptöku kemur annar aðili sem vill taka það sama upp - og þú verður lokaður og þetta er nú þegar slæmt. Þess vegna, ef þú getur flutt kynslóð sumra auðkenna til viðskiptavinarins (miðað við gagnagrunninn), er betra að gera þetta.

Það var bara fullkomið fyrir okkur að nota MD5 úr textanum - beiðni, áætlun, sniðmát,... Við reiknum það út á safnarahliðinni og „hellum“ tilbúnu auðkenninu í gagnagrunninn. Lengd MD5 og dagleg skipting gerir okkur kleift að hafa ekki áhyggjur af mögulegum árekstrum.

Margfínstilling á PostgreSQL fyrirspurnum. Kirill Borovikov (tensor)

En til þess að taka þetta allt upp hratt þurftum við að breyta upptökuferlinu sjálfu.

Hvernig skrifar þú venjulega gögn? Við erum með einhvers konar gagnasafn, við skiptum því í nokkrar töflur og AFTUM það síðan - fyrst í þá fyrstu, síðan í þá seinni, í þá þriðju... Það er óþægilegt, því við virðumst vera að skrifa einn gagnastraum í þremur skrefum í röð. Óþægilegt. Er hægt að gera það hraðar? Dós!

Til að gera þetta er nóg bara að sundra þessum flæði samhliða hvert öðru. Það kemur í ljós að við erum með villur, beiðnir, sniðmát, blokkanir, ... fljúga í aðskildum þráðum - og við skrifum þetta allt samhliða. Nóg fyrir þetta halda COPY rás stöðugt opinni fyrir hverja einstaka marktöflu.

Margfínstilling á PostgreSQL fyrirspurnum. Kirill Borovikov (tensor)

Það er að segja hjá safnara það er alltaf lækur, þar sem ég get skrifað þau gögn sem ég þarf. En svo að gagnagrunnurinn sjái þessi gögn og einhver festist ekki í því að bíða eftir að þessi gögn verði skrifuð, AFRÉTTA verður að gera hlé á ákveðnu millibili. Fyrir okkur var áhrifaríkasta tímabilið um 100 ms - við lokum því og opnum það strax aftur á sama borð. Og ef við höfum ekki nóg af einu flæði á sumum toppum, þá gerum við sameiningu upp að ákveðnum mörkum.

Að auki komumst við að því að fyrir slíkt álagssnið er hvers kyns samsöfnun, þegar gögnum er safnað í lotum, illt. Klassísk illska er INSERT ... VALUES og fleiri 1000 færslur. Vegna þess að á þeim tímapunkti hefurðu rithámark á miðlinum og allir aðrir sem reyna að skrifa eitthvað á diskinn munu bíða.

Til að losna við slík frávik skaltu einfaldlega ekki safna neinu saman, alls ekki buffer. Og ef biðminni á disk á sér stað (sem betur fer gerir Stream API í Node.js þér kleift að komast að því) - frestaðu þessari tengingu. Þegar þú færð viðburð sem hann er ókeypis aftur skaltu skrifa til hans úr uppsafnaðri biðröð. Og á meðan það er upptekið skaltu taka næsta ókeypis úr sundlauginni og skrifa til hans.

Áður en við kynntum þessa nálgun við upptöku gagna höfðum við um það bil 4K skrifaaðgerðir og þannig minnkuðum við álagið um 4 sinnum. Nú hafa þeir stækkað 6 sinnum til viðbótar vegna nýrra vöktaðra gagnagrunna - allt að 100MB/s. Og nú geymum við annála fyrir síðustu 3 mánuði í rúmmáli um 10-15TB, í von um að á aðeins þremur mánuðum muni hvaða verktaki sem er geta leyst hvaða vandamál sem er.

Við skiljum vandamálin

En einfaldlega að safna öllum þessum gögnum er gott, gagnlegt, viðeigandi, en ekki nóg - það þarf að skilja það. Vegna þess að þetta eru milljónir mismunandi áætlana á dag.

Margfínstilling á PostgreSQL fyrirspurnum. Kirill Borovikov (tensor)

En milljónir eru óviðráðanlegar, við verðum fyrst að gera „minni“. Og fyrst og fremst þarftu að ákveða hvernig þú ætlar að skipuleggja þennan „minni“ hlut.

Við höfum bent á þrjú lykilatriði:

  • hver sendi þessa beiðni
    Það er, frá hvaða forriti „kom“ það: vefviðmót, bakendi, greiðslukerfi eða eitthvað annað.
  • þar sem það gerðist
    Á hvaða tiltekna netþjóni? Vegna þess að ef þú ert með nokkra netþjóna undir einu forriti og skyndilega „verður einn heimskur“ (vegna þess að „diskurinn er rotinn“, „minni lekur“, eitthvað annað vandamál), þá þarftu að taka sérstaklega á þjóninum.
  • sem vandamálið kom fram á einn eða annan hátt

Til að skilja „hver“ sendi okkur beiðni notum við staðlað tól - stillum lotubreytu: SET application_name = '{bl-host}:{bl-method}'; — við sendum nafn viðskiptarökfræðihýsilsins sem beiðnin kemur frá og nafn aðferðarinnar eða forritsins sem kom henni af stað.

Eftir að við höfum farið framhjá „eiganda“ beiðninnar, verður hún að vera send út í annálinn - til þess stillum við breytuna log_line_prefix = ' %m [%p:%v] [%d] %r %a'. Fyrir áhugasama, kannski skoða í handbókinnihvað þýðir þetta allt saman. Það kemur í ljós að við sjáum í skránni:

  • tími
  • ferli- og viðskiptaauðkenni
  • nafn gagnagrunns
  • IP þess sem sendi þessa beiðni
  • og heiti aðferðar

Margfínstilling á PostgreSQL fyrirspurnum. Kirill Borovikov (tensor)

Þá komumst við að því að það er ekki mjög áhugavert að skoða fylgni fyrir eina beiðni milli mismunandi netþjóna. Það er ekki oft sem þú hefur aðstæður þar sem eitt forrit skrúfar jafnt upp hér og þar. En jafnvel þótt það sé það sama, skoðaðu einhvern af þessum netþjónum.

Svo hér er niðurskurðurinn "einn þjónn - einn dagur" það reyndist okkur nægja fyrir hvaða greiningu sem er.

Fyrsti greiningarhlutinn er sá sami "sýnishorn" - stytt framsetning áætlunarinnar, hreinsuð af öllum tölulegum vísbendingum. Annar niðurskurðurinn er forritið eða aðferðin og þriðja niðurskurðurinn er sérstakur áætlunarhnúturinn sem olli okkur vandamálum.

Þegar við fluttum frá sérstökum tilfellum yfir í sniðmát fengum við tvo kosti í einu:

  • margföld fækkun á fjölda hluta til greiningar
    Við verðum að greina vandamálið ekki lengur með þúsundum fyrirspurna eða áætlunum, heldur með tugum sniðmáta.
  • tímalína
    Það er, með því að draga saman „staðreyndir“ innan ákveðins hluta geturðu sýnt útlit þeirra á daginn. Og hér geturðu skilið að ef þú ert með einhvers konar mynstur sem gerist, til dæmis einu sinni á klukkutíma, en það ætti að gerast einu sinni á dag, þá ættir þú að hugsa um hvað fór úrskeiðis - hver olli því og hvers vegna, ætti það kannski að vera hér ætti ekki. Þetta er önnur ótöluleg, eingöngu sjónræn, greiningaraðferð.

Margfínstilling á PostgreSQL fyrirspurnum. Kirill Borovikov (tensor)

Aðferðirnar sem eftir eru eru byggðar á vísbendingunum sem við tökum út úr áætluninni: hversu oft slíkt mynstur átti sér stað, heildar- og meðaltími, hversu mikið af gögnum var lesið af disknum og hversu mikið úr minni ...

Vegna þess að þú kemur til dæmis á greiningarsíðuna fyrir gestgjafann, sjáðu - eitthvað er farið að lesa of mikið á disknum. Diskurinn á þjóninum ræður ekki við það - hver les af honum?

Og þú getur flokkað eftir hvaða dálki sem er og ákveðið hvað þú ætlar að takast á við núna - álagið á örgjörvan eða diskinn, eða heildarfjöldi beiðna... Við flokkuðum það, skoðuðum þær „efstu“, laguðum það og setti út nýja útgáfu af forritinu.
[myndbandsfyrirlestur]

Og strax geturðu séð mismunandi forrit sem koma með sama sniðmát frá beiðni eins og SELECT * FROM users WHERE login = 'Vasya'. Frontend, backend, processing... Og þú veltir fyrir þér hvers vegna vinnsla myndi lesa notandann ef hann hefur ekki samskipti við hann.

Hið gagnstæða er að sjá strax af forritinu hvað það gerir. Til dæmis er framhliðin þetta, þetta, þetta og þetta einu sinni á klukkustund (tímalínan hjálpar). Og spurningin vaknar strax: það virðist ekki vera hlutverk framenda að gera eitthvað einu sinni á klukkustund...

Margfínstilling á PostgreSQL fyrirspurnum. Kirill Borovikov (tensor)

Eftir nokkurn tíma áttuðum við okkur á því að okkur vantaði samanlagt tölfræði eftir áætlunarhnútum. Við einangruðum frá áætlunum aðeins þá hnúta sem gera eitthvað við gögnin í töflunum sjálfum (lesa/skrifa þær eftir vísitölu eða ekki). Reyndar er aðeins einum þætti bætt við miðað við fyrri mynd - hversu margar færslur færði þessi hnútur okkur?, og hversu mörgum var hent (Raðir fjarlægðar með síu).

Þú ert ekki með viðeigandi vísitölu á plötunni, þú leggur fram beiðni til hennar, hún flýgur framhjá vísitölunni, fellur í Seq Scan ... þú hefur síað út allar færslur nema eina. Af hverju þarftu 100M síaðar færslur á dag? Er ekki betra að rúlla upp vísitölunni?

Margfínstilling á PostgreSQL fyrirspurnum. Kirill Borovikov (tensor)

Eftir að hafa greint allar áætlanirnar hnút fyrir hnút komumst við að því að það eru nokkur dæmigerð mannvirki í áætlununum sem eru mjög líkleg til að líta grunsamlega út. Og það væri gaman að segja verktaki: "Vinur, hér lestu fyrst eftir vísitölu, flokkaðu síðan og klipptu síðan af" - að jafnaði er ein skrá.

Allir sem skrifuðu fyrirspurnir hafa líklega rekist á þetta mynstur: „Gefðu mér síðustu pöntunina fyrir Vasya, dagsetningu hennar.“ Og ef þú ert ekki með vísitölu eftir dagsetningu, eða það er engin dagsetning í vísitölunni sem þú notaðir, þá muntu stíga á nákvæmlega sömu „hrífuna“.

En við vitum að þetta er „rake“ - svo hvers vegna ekki að segja framkvæmdaraðilanum strax hvað hann ætti að gera. Í samræmi við það, þegar áætlun er opnuð núna, sér verktaki okkar strax fallega mynd með ábendingum, þar sem þeir segja honum strax: "Þú átt í vandræðum hér og þar, en þau eru leyst svona og þannig."

Þess vegna hefur reynslan sem þurfti til að leysa vandamál í upphafi og nú minnkað verulega. Þetta er svona tól sem við höfum.

Margfínstilling á PostgreSQL fyrirspurnum. Kirill Borovikov (tensor)

Heimild: www.habr.com

Bæta við athugasemd