Optimeiddio swmp o ymholiadau PostgreSQL. Kirill Borovikov (Tensor)

Mae'r adroddiad yn cyflwyno rhai dulliau sy'n caniatáu monitro perfformiad ymholiadau SQL pan fo miliynau ohonynt y dydd, ac mae cannoedd o weinyddion PostgreSQL wedi'u monitro.

Pa atebion technegol sy'n ein galluogi i brosesu cymaint o wybodaeth yn effeithlon, a sut mae hyn yn gwneud bywyd datblygwr cyffredin yn haws?


Pwy sydd â diddordeb? dadansoddiad o broblemau penodol a thechnegau optimeiddio amrywiol Ymholiadau SQL a datrys problemau DBA nodweddiadol yn PostgreSQL - gallwch chi hefyd darllen cyfres o erthyglau ar y pwnc hwn.

Optimeiddio swmp o ymholiadau PostgreSQL. Kirill Borovikov (Tensor)
Fy enw i yw Kirill Borovikov, rwy'n cynrychioli Cwmni tensor. Yn benodol, rwy'n arbenigo mewn gweithio gyda chronfeydd data yn ein cwmni.

Heddiw, dywedaf wrthych sut yr ydym yn gwneud y gorau o ymholiadau, pan nad oes angen i chi “ddewis” perfformiad un ymholiad, ond datrys y broblem yn llu. Pan fydd miliynau o geisiadau, ac mae angen ichi ddod o hyd i rai ymagweddau at ddatrysiad y broblem fawr hon.

Yn gyffredinol, Tensor ar gyfer miliwn o'n cleientiaid yn VLSI yw ein cais: rhwydwaith cymdeithasol corfforaethol, datrysiadau ar gyfer cyfathrebu fideo, ar gyfer llif dogfennau mewnol ac allanol, systemau cyfrifo ar gyfer cyfrifyddu a warysau,... Hynny yw, “mega-combine” o'r fath ar gyfer rheoli busnes integredig, lle mae mwy na 100 o wahanol prosiectau mewnol.

Er mwyn sicrhau eu bod i gyd yn gweithio ac yn datblygu fel arfer, mae gennym 10 canolfan ddatblygu ledled y wlad, gyda mwy ynddynt 1000 o ddatblygwyr.

Rydym wedi bod yn gweithio gyda PostgreSQL ers 2008 ac wedi cronni llawer iawn o'r hyn rydym yn ei brosesu - data cleientiaid, ystadegol, dadansoddol, data o systemau gwybodaeth allanol - mwy na 400TB. Mae tua 250 o weinyddion yn cael eu cynhyrchu yn unig, ac i gyd mae tua 1000 o weinyddion cronfa ddata yr ydym yn eu monitro.

Optimeiddio swmp o ymholiadau PostgreSQL. Kirill Borovikov (Tensor)

Mae SQL yn iaith ddatganiadol. Rydych chi'n disgrifio nid “sut” y dylai rhywbeth weithio, ond “beth” rydych chi am ei gyflawni. Mae'r DBMS yn gwybod yn well sut i ymuno - sut i gysylltu'ch byrddau, pa amodau i'w gosod, beth fydd yn mynd trwy'r mynegai, beth na fydd...

Mae rhai DBMSs yn derbyn awgrymiadau: “Na, cysylltwch y ddau dabl hyn mewn ciw o'r fath,” ond ni all PostgreSQL wneud hyn. Dyma safbwynt ymwybodol datblygwyr blaenllaw: “Byddai’n well gennym orffen y optimizer ymholiad na chaniatáu i ddatblygwyr ddefnyddio rhyw fath o awgrymiadau.”

Ond, er gwaethaf y ffaith nad yw PostgreSQL yn caniatáu i'r “tu allan” reoli ei hun, mae'n caniatáu'n berffaith gweld beth sy'n digwydd y tu mewn iddopan fyddwch chi'n rhedeg eich ymholiad, a lle mae'n cael problemau.

Optimeiddio swmp o ymholiadau PostgreSQL. Kirill Borovikov (Tensor)

Yn gyffredinol, pa broblemau clasurol sydd gan ddatblygwr [i DBA] fel arfer? “ Yma cyflawnasom y cais, a mae popeth yn araf gyda ni, mae popeth yn hongian, mae rhywbeth yn digwydd... Rhyw fath o drafferth!”

Mae'r rhesymau bron bob amser yr un peth:

  • algorithm ymholiad aneffeithlon
    Datblygwr: “Nawr rydw i'n rhoi 10 bwrdd iddo yn SQL trwy YMUNWCH...” - ac yn disgwyl y bydd ei amodau yn wyrthiol i bob pwrpas yn “ddi-gysylltiedig” a bydd yn cael popeth yn gyflym. Ond nid yw gwyrthiau yn digwydd, ac mae unrhyw system gyda'r fath amrywioldeb (10 tablau mewn un FROM) bob amser yn rhoi rhyw fath o gamgymeriad. [erthygl]
  • ystadegau hen ffasiwn
    Mae'r pwynt hwn yn berthnasol iawn yn benodol ar gyfer PostgreSQL, pan wnaethoch chi “arllwys” set ddata fawr ar y gweinydd, gwneud cais, ac mae'n “sexcanits” eich tabled. Oherwydd ddoe roedd 10 cofnod ynddo, a heddiw mae 10 miliwn, ond nid yw PostgreSQL yn ymwybodol o hyn eto, ac mae angen inni ddweud wrtho amdano. [erthygl]
  • "plwg" ar adnoddau
    Rydych chi wedi gosod cronfa ddata fawr sydd wedi'i llwytho'n drwm ar weinydd gwan nad oes ganddo ddigon o berfformiad disg, cof na phrosesydd. A dyna i gyd... Rhywle mae yna nenfwd perfformiad na allwch chi neidio uwch ei ben mwyach.
  • blocio
    Mae hwn yn bwynt anodd, ond maent yn fwyaf perthnasol ar gyfer amrywiol ymholiadau addasu (NODWCH, DIWEDDARIAD, DILEU) - mae hwn yn bwnc mawr ar wahân.

Cael cynllun

...Ac am bopeth arall ni angen cynllun! Mae angen inni weld beth sy'n digwydd y tu mewn i'r gweinydd.

Optimeiddio swmp o ymholiadau PostgreSQL. Kirill Borovikov (Tensor)

Mae cynllun cyflawni ymholiad ar gyfer PostgreSQL yn goeden o'r algorithm gweithredu ymholiad mewn cynrychioliad testun. Yr union algorithm y canfuwyd, o ganlyniad i ddadansoddiad gan y cynlluniwr, oedd yr un mwyaf effeithiol.

Mae pob nod coeden yn weithred: adfer data o dabl neu fynegai, adeiladu map didau, uno dau dabl, uno, croestorri, neu eithrio detholiadau. Mae cyflawni ymholiad yn golygu cerdded trwy nodau'r goeden hon.

I gael y cynllun ymholiad, y ffordd hawsaf yw gweithredu'r datganiad EXPLAIN. I gael gyda'r holl briodoleddau go iawn, hynny yw, gweithredu ymholiad ar y sylfaen mewn gwirionedd - EXPLAIN (ANALYZE, BUFFERS) SELECT ....

Y rhan ddrwg: pan fyddwch chi'n ei redeg, mae'n digwydd "yma ac yn awr", felly dim ond ar gyfer dadfygio lleol y mae'n addas. Os cymerwch weinydd llawn llwyth sydd o dan lif cryf o newidiadau data, a'ch bod yn gweld: “O! Yma mae gennym weithrediad arafgwersylla cais." Hanner awr, awr yn ôl - tra oeddech chi'n rhedeg ac yn cael y cais hwn o'r logiau, gan ddod ag ef yn ôl i'r gweinydd, newidiodd eich set ddata gyfan ac ystadegau. Rydych chi'n ei redeg i ddadfygio - ac mae'n rhedeg yn gyflym! Ac ni allwch ddeall pam, pam oedd yn araf.

Optimeiddio swmp o ymholiadau PostgreSQL. Kirill Borovikov (Tensor)

Er mwyn deall beth ddigwyddodd yn union ar hyn o bryd pan weithredwyd y cais ar y gweinydd, ysgrifennodd pobl smart modiwl auto_explain. Mae'n bresennol ym mron pob un o'r dosbarthiadau PostgreSQL mwyaf cyffredin, a gellir ei actifadu yn y ffeil ffurfweddu.

Os yw'n sylweddoli bod rhai ceisiadau yn rhedeg yn hirach na'r terfyn y dywedasoch wrtho, mae'n gwneud hynny “ciplun” o gynllun y cais hwn ac yn eu hysgrifennu gyda’i gilydd yn y log.

Optimeiddio swmp o ymholiadau PostgreSQL. Kirill Borovikov (Tensor)

Mae popeth i'w weld yn iawn nawr, awn i'r log a gweld yno... [testun footcloth]. Ond ni allwn ddweud dim amdano, heblaw am y ffaith ei fod yn gynllun rhagorol oherwydd cymerodd 11ms i'w weithredu.

Mae popeth i'w weld yn iawn - ond does dim byd yn glir beth ddigwyddodd mewn gwirionedd. Ar wahân i'r amser cyffredinol, nid ydym yn gweld unrhyw beth mewn gwirionedd. Oherwydd nid yw edrych ar y fath “oen” o destun plaen yn weledol yn gyffredinol.

Ond hyd yn oed os nad yw'n amlwg, hyd yn oed os yw'n anghyfleus, mae yna broblemau mwy sylfaenol:

  • Mae'r nod yn nodi swm adnoddau yr is-goeden gyfan dano. Hynny yw, ni allwch ddarganfod faint o amser a dreuliwyd ar y Sgan Mynegai penodol hwn os oes rhywfaint o gyflwr nythu oddi tano. Rhaid inni edrych yn ddeinamig i weld a oes “plant” a newidynnau amodol, CTEs y tu mewn - a thynnu hyn i gyd “yn ein meddyliau”.
  • Ail bwynt: yr amser a nodir ar y nod yw amser gweithredu nod sengl. Os gweithredwyd y nod hwn o ganlyniad, er enghraifft, i ddolen trwy gofnodion tabl sawl gwaith, yna mae nifer y dolenni - cylchoedd y nod hwn - yn cynyddu yn y cynllun. Ond mae'r amser gweithredu atomig ei hun yn aros yr un fath o ran cynllun. Hynny yw, er mwyn deall am ba mor hir y cyflawnwyd y nod hwn, mae angen i chi luosi un peth â'r llall - eto, "yn eich pen."

Mewn sefyllfaoedd o'r fath, deallwch "Pwy yw'r cyswllt gwannaf?" bron yn amhosibl. Felly, mae hyd yn oed y datblygwyr eu hunain yn ysgrifennu yn y “llawlyfr” hynny “Mae deall cynllun yn gelfyddyd y mae’n rhaid ei dysgu, profiad...”.

Ond mae gennym ni 1000 o ddatblygwyr, ac ni allwch gyfleu'r profiad hwn i bob un ohonynt. Fi, ti, mae'n gwybod, ond nid yw rhywun draw yn gwybod mwyach. Efallai y bydd yn dysgu, neu efallai ddim, ond mae angen iddo weithio nawr - a ble byddai'n cael y profiad hwn?

Cynllun delweddu

Felly, sylweddolasom, er mwyn ymdrin â’r problemau hyn, fod angen inni delweddu'r cynllun yn dda. [erthygl]

Optimeiddio swmp o ymholiadau PostgreSQL. Kirill Borovikov (Tensor)

Aethon ni “drwy'r farchnad” yn gyntaf - gadewch i ni edrych ar y Rhyngrwyd i weld beth sy'n bodoli hyd yn oed.

Ond daeth i'r amlwg mai ychydig iawn o atebion cymharol “fyw” sy'n datblygu fwy neu lai - yn llythrennol, dim ond un: esbonio.depesz.com gan Hubert Lubaczewski. Pan fyddwch chi'n mynd i mewn i'r maes “feed” cynrychioliad testun o'r cynllun, mae'n dangos tabl i chi gyda'r data wedi'i ddosrannu:

  • amser prosesu nod ei hun
  • cyfanswm amser ar gyfer yr is-goeden gyfan
  • nifer y cofnodion a adalwyd a ddisgwylir yn ystadegol
  • y corff nod ei hun

Mae gan y gwasanaeth hwn hefyd y gallu i rannu archif o ddolenni. Fe wnaethoch chi daflu'ch cynllun i mewn yno a dweud: “Hei, Vasya, dyma ddolen, mae rhywbeth o'i le yno.”

Optimeiddio swmp o ymholiadau PostgreSQL. Kirill Borovikov (Tensor)

Ond mae yna broblemau bach hefyd.

Yn gyntaf, llawer iawn o “gopïo-past”. Rydych chi'n cymryd darn o'r log, yn ei lynu yno, ac eto, ac eto.

Yn ail, mae'r dim dadansoddiad o faint o ddata a ddarllenwyd — yr un byfferau ag allbwn EXPLAIN (ANALYZE, BUFFERS), nid ydym yn ei weld yma. Yn syml, nid yw'n gwybod sut i'w dadosod, eu deall a gweithio gyda nhw. Pan fyddwch chi'n darllen llawer o ddata ac yn sylweddoli y gallech fod yn camddyrannu'r storfa ddisg a chof, mae'r wybodaeth hon yn bwysig iawn.

Y trydydd pwynt negyddol yw datblygiad gwan iawn y prosiect hwn. Mae'r ymrwymiadau yn fach iawn, mae'n dda unwaith bob chwe mis, ac mae'r cod yn Perl.

Optimeiddio swmp o ymholiadau PostgreSQL. Kirill Borovikov (Tensor)

Ond “telyneg” yw hyn i gyd, fe allen ni rywsut fyw gyda hyn, ond mae un peth a’n trodd yn fawr oddi wrth y gwasanaeth hwn. Mae'r rhain yn wallau yn y dadansoddiad o Fynegiad Tabl Cyffredin (CTE) a nodau deinamig amrywiol fel InitPlan/SubPlan.

Os ydych chi'n credu'r llun hwn, yna mae cyfanswm amser gweithredu pob nod unigol yn fwy na chyfanswm amser gweithredu'r cais cyfan. Mae'n syml - ni chafodd amser cenhedlaeth y CTE hwn ei dynnu o'r nod Scan CTE. Felly, nid ydym bellach yn gwybod yr ateb cywir i ba mor hir a gymerodd y sgan CTE ei hun.

Optimeiddio swmp o ymholiadau PostgreSQL. Kirill Borovikov (Tensor)

Yna sylweddolon ni ei bod hi'n amser ysgrifennu ein rhai ein hunain - hurray! Dywed pob datblygwr: “Nawr byddwn yn ysgrifennu ein rhai ein hunain, bydd yn hynod hawdd!”

Fe wnaethon ni gymryd pentwr sy'n nodweddiadol ar gyfer gwasanaethau gwe: craidd yn seiliedig ar Node.js + Express, defnyddio Bootstrap a D3.js ar gyfer diagramau hardd. Ac roedd ein disgwyliadau wedi'u cyfiawnhau'n llawn - cawsom y prototeip cyntaf mewn 2 wythnos:

  • parser cynllun personol
    Hynny yw, nawr gallwn ddosrannu unrhyw gynllun o'r rhai a gynhyrchwyd gan PostgreSQL.
  • dadansoddiad cywir o nodau deinamig - Sgan CTE, InitPlan, SubPlan
  • dadansoddiad o ddosbarthiad byfferau - lle darllenir tudalennau data o'r cof, ble o'r storfa leol, ble o ddisg
  • wedi cael eglurder
    Er mwyn peidio â “cloddio” hyn i gyd yn y log, ond i weld y “dolen gwannaf” ar unwaith yn y llun.

Optimeiddio swmp o ymholiadau PostgreSQL. Kirill Borovikov (Tensor)

Cawsom rywbeth fel hyn, gan gynnwys amlygu cystrawen. Ond fel arfer nid yw ein datblygwyr bellach yn gweithio gyda chynrychiolaeth gyflawn o'r cynllun, ond gydag un byrrach. Wedi'r cyfan, rydym eisoes wedi dosrannu'r holl rifau a'u taflu i'r chwith ac i'r dde, ac yn y canol dim ond y llinell gyntaf a adawsom, pa fath o nod ydyw: CTE Scan, CTE generation neu Seq Scan yn ôl rhyw arwydd.

Dyma'r gynrychiolaeth gryno a alwn templed cynllun.

Optimeiddio swmp o ymholiadau PostgreSQL. Kirill Borovikov (Tensor)

Beth arall fyddai'n gyfleus? Byddai’n gyfleus gweld pa gyfran o’n holl amser sy’n cael ei neilltuo i ba nod – a’i “glynu” wrth yr ochr siart cylch.

Rydyn ni'n pwyntio at y nod a gweld - mae'n ymddangos bod Seq Scan wedi cymryd llai na chwarter o'r cyfanswm amser, a chymerwyd y 3/4 sy'n weddill gan CTE Scan. Arswyd! Nodyn bach yw hwn am “gyfradd tân” CTE Scan os ydych chi'n eu defnyddio'n weithredol yn eich ymholiadau. Nid ydynt yn gyflym iawn - maent yn israddol hyd yn oed i sganio bwrdd rheolaidd. [erthygl] [erthygl]

Ond fel arfer mae diagramau o'r fath yn fwy diddorol, yn fwy cymhleth, pan fyddwn yn pwyntio ar unwaith at segment a gweld, er enghraifft, bod mwy na hanner yr amser y mae rhai Seq Scan yn “bwyta”. Ar ben hynny, roedd rhyw fath o Hidlydd y tu mewn, cafodd llawer o gofnodion eu taflu yn ôl iddo ... Gallwch chi daflu'r llun hwn yn uniongyrchol at y datblygwr a dweud: “Vasya, mae popeth yn ddrwg yma i chi! Darganfyddwch, edrychwch - mae rhywbeth o'i le!"

Optimeiddio swmp o ymholiadau PostgreSQL. Kirill Borovikov (Tensor)

Yn naturiol, roedd rhai “cribinio” dan sylw.

Y peth cyntaf y daethom ar ei draws oedd y broblem talgrynnu. Mae amser pob nod unigol yn y cynllun wedi'i nodi gyda chywirdeb o 1 μs. A phan fydd nifer y cylchoedd nod yn fwy, er enghraifft, 1000 - ar ôl gweithredu rhannodd PostgreSQL “o fewn cywirdeb”, yna wrth gyfrifo yn ôl cawn gyfanswm yr amser “rhywle rhwng 0.95ms a 1.05ms”. Pan fydd y cyfrif yn mynd i ficroeiliadau, mae hynny'n iawn, ond pan mae eisoes [mili] eiliadau, mae'n rhaid i chi ystyried y wybodaeth hon wrth “ddatod” adnoddau i nodau'r cynllun “pwy a ddefnyddiodd faint”.

Optimeiddio swmp o ymholiadau PostgreSQL. Kirill Borovikov (Tensor)

Yr ail bwynt, sy'n fwy cymhleth, yw dosbarthiad adnoddau (y byfferau hynny) ymhlith nodau deinamig. Costiodd hyn 2 wythnos gyntaf y prototeip i ni ynghyd â 4 wythnos arall.

Mae'n eithaf hawdd cael y math hwn o broblem - rydyn ni'n gwneud CTE ac i fod yn darllen rhywbeth ynddo. Mewn gwirionedd, mae PostgreSQL yn “smart” ac ni fydd yn darllen unrhyw beth yn uniongyrchol yno. Yna rydyn ni'n cymryd y cofnod cyntaf ohono, ac iddo'r cant a'r cyntaf o'r un CTE.

Optimeiddio swmp o ymholiadau PostgreSQL. Kirill Borovikov (Tensor)

Rydyn ni'n edrych ar y cynllun ac yn deall - mae'n rhyfedd, mae gennym ni 3 byffer (tudalennau data) wedi'u “bwyta” yn Seq Scan, 1 arall yn CTE Scan, a 2 arall yn yr ail CTE Scan. Hynny yw, os byddwn ni'n crynhoi popeth, fe gawn ni 6, ond dim ond 3 rydyn ni'n eu darllen o'r dabled! Nid yw CTE Scan yn darllen unrhyw beth o unrhyw le, ond mae'n gweithio'n uniongyrchol gyda chof y broses. Hynny yw, mae rhywbeth yn amlwg o'i le yma!

Yn wir, mae'n ymddangos mai dyma'r holl 3 tudalen o ddata y gofynnwyd amdanynt gan Seq Scan, gofynnodd 1 yn gyntaf am y Sgan CTE 1af, ac yna darllenwyd yr 2il, a darllenwyd 2 arall iddo. Hynny yw, cyfanswm o Data darllenwyd 3 tudalen, nid 6.

Optimeiddio swmp o ymholiadau PostgreSQL. Kirill Borovikov (Tensor)

Ac arweiniodd y llun hwn ni at y ddealltwriaeth nad yw gweithredu cynllun bellach yn goeden, ond yn syml yn rhyw fath o graff acyclic. A chawsom ddiagram fel hyn, fel ein bod yn deall “beth ddaeth o ble yn y lle cyntaf.” Hynny yw, dyma ni'n creu CTE o pg_class, a gofyn amdano ddwywaith, a threuliwyd bron y cyfan o'n hamser ar y gangen pan ofynnon ni amdano'r 2il dro. Mae'n amlwg bod darllen y cofnod 101st yn llawer drutach na darllen y cofnod 1af o'r dabled yn unig.

Optimeiddio swmp o ymholiadau PostgreSQL. Kirill Borovikov (Tensor)

Fe wnaethon ni anadlu allan am ychydig. Dywedasant: “Nawr, Neo, rydych chi'n gwybod kung fu! Nawr mae ein profiad yn iawn ar eich sgrin. Nawr gallwch chi ei ddefnyddio." [erthygl]

Cydgrynhoi log

Anadlodd ein 1000 o ddatblygwyr ochenaid o ryddhad. Ond roeddem yn deall mai dim ond cannoedd o weinyddion “brwydro” sydd gennym, ac nid yw'r holl “gopïo past” hwn ar ran y datblygwyr yn gyfleus o gwbl. Sylweddolon ni fod yn rhaid i ni ei gasglu ein hunain.

Optimeiddio swmp o ymholiadau PostgreSQL. Kirill Borovikov (Tensor)

Yn gyffredinol, mae modiwl safonol sy'n gallu casglu ystadegau, fodd bynnag, mae angen ei actifadu hefyd yn y ffurfwedd - hwn modiwl pg_stat_statements. Ond nid oedd yn ein siwtio ni.

Yn gyntaf, mae'n aseinio i'r un ymholiadau gan ddefnyddio gwahanol gynlluniau o fewn yr un gronfa ddata gwahanol QueryIds. Hynny yw, os gwnewch chi gyntaf SET search_path = '01'; SELECT * FROM user LIMIT 1;ac yna SET search_path = '02'; a'r un cais, yna bydd gan ystadegau'r modiwl hwn gofnodion gwahanol, ac ni fyddaf yn gallu casglu ystadegau cyffredinol yn benodol yng nghyd-destun proffil y cais hwn, heb gymryd y cynlluniau i ystyriaeth.

Yr ail bwynt a'n rhwystrodd rhag ei ​​ddefnyddio yw diffyg cynlluniau. Hynny yw, nid oes cynllun, dim ond y cais ei hun sydd. Rydym yn gweld beth oedd yn arafu, ond nid ydym yn deall pam. A dyma ni'n dychwelyd at y broblem o set ddata sy'n newid yn gyflym.

A'r eiliad olaf - diffyg "ffeithiau". Hynny yw, ni allwch roi sylw i enghraifft benodol o gyflawni ymholiad - nid oes dim, dim ond ystadegau cyfanredol sydd. Er ei bod hi'n bosibl gweithio gyda hyn, mae'n anodd iawn.

Optimeiddio swmp o ymholiadau PostgreSQL. Kirill Borovikov (Tensor)

Felly, fe benderfynon ni frwydro yn erbyn copi-gludo a dechrau ysgrifennu casglwr.

Mae'r casglwr yn cysylltu trwy SSH, yn sefydlu cysylltiad diogel â'r gweinydd gyda'r gronfa ddata gan ddefnyddio tystysgrif, a tail -F “yn glynu” wrtho yn y ffeil log. Felly yn y sesiwn hon rydym yn cael “drych” cyflawn o'r ffeil log gyfan, y mae'r gweinydd yn ei gynhyrchu. Mae'r llwyth ar y gweinydd ei hun yn fach iawn, oherwydd nid ydym yn dosrannu unrhyw beth yno, rydyn ni'n adlewyrchu'r traffig yn unig.

Gan ein bod eisoes wedi dechrau ysgrifennu'r rhyngwyneb yn Node.js, fe wnaethom barhau i ysgrifennu'r casglwr ynddo. Ac mae'r dechnoleg hon wedi cyfiawnhau ei hun, oherwydd mae'n gyfleus iawn defnyddio JavaScript i weithio gyda data testun sydd wedi'i fformatio'n wan, sef y log. Ac mae seilwaith Node.js ei hun fel platfform backend yn caniatáu ichi weithio'n hawdd ac yn gyfleus gyda chysylltiadau rhwydwaith, ac yn wir gydag unrhyw ffrydiau data.

Yn unol â hynny, rydym yn "ymestyn" dau gysylltiad: y cyntaf i "wrando" ar y log ei hun a'i gymryd i ni ein hunain, a'r ail i ofyn y sylfaen o bryd i'w gilydd. “Ond mae’r log yn dangos bod yr arwydd gydag oid 123 wedi’i rwystro,” ond nid yw hyn yn golygu unrhyw beth i’r datblygwr, a byddai’n braf gofyn i’r gronfa ddata, “Beth yw OID = 123 beth bynnag?” Ac felly rydym o bryd i'w gilydd yn gofyn i'r sylfaen yr hyn nad ydym yn ei wybod amdanom ein hunain eto.

Optimeiddio swmp o ymholiadau PostgreSQL. Kirill Borovikov (Tensor)

“Dim ond un peth na wnaethoch chi ei ystyried, mae yna rywogaeth o wenyn tebyg i eliffant!..” Dechreuon ni ddatblygu’r system hon pan oedden ni eisiau monitro 10 gweinydd. Y mwyaf hanfodol yn ein dealltwriaeth, lle cododd rhai problemau a oedd yn anodd delio â nhw. Ond yn ystod y chwarter cyntaf, cawsom gant ar gyfer monitro - oherwydd bod y system yn gweithio, roedd pawb ei eisiau, roedd pawb yn gyfforddus.

Mae angen ychwanegu hyn i gyd, mae'r llif data yn fawr ac yn weithredol. Mewn gwirionedd, yr hyn yr ydym yn ei fonitro, yr hyn y gallwn ymdrin ag ef, yw'r hyn a ddefnyddiwn. Rydym hefyd yn defnyddio PostgreSQL fel storfa ddata. Ac nid oes dim yn gyflymach i “arllwys” data iddo na'r gweithredwr COPY Ddim eto.

Ond yn syml, nid “arllwys” data yw ein technoleg mewn gwirionedd. Oherwydd os oes gennych tua 50k o geisiadau yr eiliad ar gant o weinyddion, yna bydd hyn yn cynhyrchu 100-150GB o logiau y dydd. Felly, roedd yn rhaid i ni “dorri” y sylfaen yn ofalus.

Yn gyntaf, fe wnaethom rhaniad yn ystod y dydd, oherwydd, ar y cyfan, nid oes gan neb ddiddordeb yn y cydberthynas rhwng dyddiau. Pa wahaniaeth y mae'n ei wneud i'r hyn a oedd gennych ddoe, pe baech yn cyflwyno fersiwn newydd o'r cais heno - a rhai ystadegau newydd yn barod.

Yn ail, fe wnaethon ni ddysgu (cawsom ein gorfodi) yn gyflym iawn, iawn i ysgrifennu gan ddefnyddio COPY. Hynny yw, nid yn unig COPYam ei fod yn gyflymach na INSERT, a hyd yn oed yn gyflymach.

Optimeiddio swmp o ymholiadau PostgreSQL. Kirill Borovikov (Tensor)

Y trydydd pwynt - roedd yn rhaid i mi sbardunau rhoi'r gorau, yn y drefn honno, ac allweddi tramor. Hynny yw, nid oes gennym unrhyw uniondeb cyfeiriadol o gwbl. Oherwydd os oes gennych chi dabl sydd â phâr o FKs, a'ch bod chi'n dweud yn strwythur y gronfa ddata “dyma gofnod log y mae FK yn cyfeirio ato, er enghraifft, at grŵp o gofnodion,” yna pan fyddwch chi'n ei fewnosod, PostgreSQL dim byd ar ôl ond sut i'w gymryd a'i wneud yn onest SELECT 1 FROM master_fk1_table WHERE ... gyda'r dynodwr yr ydych yn ceisio ei fewnosod - dim ond i wirio bod y cofnod hwn yn bresennol yno, nad ydych yn “torri i ffwrdd” yr Allwedd Dramor hon gyda'ch mewnosodiad.

Yn lle un cofnod i’r tabl targed a’i fynegeion, cawn y fantais ychwanegol o ddarllen o’r holl dablau y mae’n cyfeirio atynt. Ond nid oes angen hyn o gwbl arnom - ein tasg ni yw cofnodi cymaint â phosibl a chyn gynted â phosibl gyda'r llwyth lleiaf. Felly FK - lawr!

Y pwynt nesaf yw agregu a stwnsio. I ddechrau, fe wnaethon ni eu gweithredu yn y gronfa ddata - wedi'r cyfan, mae'n gyfleus ar unwaith, pan fydd cofnod yn cyrraedd, ei wneud mewn rhyw fath o dabled "plus one" reit yn y sbardun. Wel, mae'n gyfleus, ond yr un peth drwg - rydych chi'n mewnosod un cofnod, ond yn cael eich gorfodi i ddarllen ac ysgrifennu rhywbeth arall o dabl arall. Ar ben hynny, nid yn unig rydych chi'n darllen ac yn ysgrifennu, rydych chi hefyd yn ei wneud bob tro.

Nawr dychmygwch fod gennych dabl lle rydych chi'n cyfrif nifer y ceisiadau sydd wedi mynd trwy westeiwr penodol: +1, +1, +1, ..., +1. Ac mewn egwyddor, nid oes angen hyn arnoch chi - mae'r cyfan yn bosibl swm er cof ar y casglwr ac anfon i'r gronfa ddata ar yr un pryd +10.

Oes, rhag ofn y bydd rhai problemau, efallai y bydd eich uniondeb rhesymegol yn “disgyn”, ond mae hwn yn achos bron yn afrealistig - oherwydd bod gennych weinydd arferol, mae ganddo fatri yn y rheolydd, mae gennych log trafodion, log ar y system ffeiliau... Yn gyffredinol, nid yw'n werth chweil. Nid yw'r golled cynhyrchiant a gewch o redeg sbardunau / FK yn werth y gost yr ewch iddi.

Mae'r un peth gyda stwnsio. Mae cais penodol yn mynd atoch chi, rydych chi'n cyfrifo dynodwr penodol ohono yn y gronfa ddata, yn ei ysgrifennu i'r gronfa ddata ac yna'n ei ddweud wrth bawb. Mae popeth yn iawn nes, ar adeg recordio, mae ail berson yn dod atoch chi sydd eisiau recordio'r un peth - a'ch bod chi'n cael eich rhwystro, ac mae hyn eisoes yn ddrwg. Felly, os gallwch chi drosglwyddo'r genhedlaeth o rai IDau i'r cleient (o'i gymharu â'r gronfa ddata), mae'n well gwneud hyn.

Roedd yn berffaith i ni ddefnyddio MD5 o'r testun - cais, cynllun, templed,... Rydym yn ei gyfrifo ar ochr y casglwr, ac yn “arllwys” yr ID parod i'r gronfa ddata. Mae hyd MD5 a rhaniad dyddiol yn ein galluogi i beidio â phoeni am wrthdrawiadau posibl.

Optimeiddio swmp o ymholiadau PostgreSQL. Kirill Borovikov (Tensor)

Ond er mwyn cofnodi hyn i gyd yn gyflym, roedd angen i ni addasu'r drefn recordio ei hun.

Sut ydych chi'n ysgrifennu data fel arfer? Mae gennym ni ryw fath o set ddata, rydyn ni'n ei rhannu'n sawl tabl, ac yna'n COPI - yn gyntaf i'r cyntaf, yna i'r ail, i'r trydydd... Mae'n anghyfleus, oherwydd mae'n ymddangos ein bod ni'n ysgrifennu un ffrwd data mewn tri cham dilyniannol. Annifyr. A ellir ei wneud yn gyflymach? Gall!

I wneud hyn, mae'n ddigon i ddadelfennu'r llifau hyn ochr yn ochr â'i gilydd. Mae'n ymddangos bod gennym wallau, ceisiadau, templedi, blociau, ... hedfan mewn edafedd ar wahân - ac rydym yn ysgrifennu'r cyfan yn gyfochrog. Digon i hyn cadw sianel COPY ar agor yn gyson ar gyfer pob tabl targed unigol.

Optimeiddio swmp o ymholiadau PostgreSQL. Kirill Borovikov (Tensor)

Hynny yw, wrth y casglwr mae nant bob amser, y gallaf ysgrifennu'r data sydd ei angen arnaf. Ond fel bod y gronfa ddata yn gweld y data hwn, ac nad yw rhywun yn mynd yn sownd yn aros i'r data hwn gael ei ysgrifennu, Rhaid torri ar draws COPI ar adegau penodol. I ni, y cyfnod mwyaf effeithiol oedd tua 100ms - rydyn ni'n ei gau ac yn ei agor eto i'r un bwrdd ar unwaith. Ac os nad oes gennym ni ddigon o un llif yn ystod rhai uchafbwyntiau, yna rydyn ni'n cronni hyd at derfyn penodol.

Yn ogystal, ar gyfer proffil llwyth o'r fath, fe wnaethom ddarganfod bod unrhyw agregu, pan fydd cofnodion yn cael eu casglu fesul tipyn, yn ddrwg. Drygioni clasurol yw INSERT ... VALUES a 1000 o gofnodion pellach. Oherwydd ar y pwynt hwnnw mae gennych uchafbwynt ysgrifennu ar y cyfryngau, a bydd pawb arall sy'n ceisio ysgrifennu rhywbeth i'r ddisg yn aros.

I gael gwared ar anghysondebau o'r fath, peidiwch â chyfuno unrhyw beth, peidiwch â byffer o gwbl. Ac os bydd byffro i ddisg yn digwydd (yn ffodus, mae'r API Stream yn Node.js yn caniatáu ichi ddarganfod) - gohirio'r cysylltiad hwn. Pan fyddwch yn derbyn digwyddiad ei fod yn rhad ac am ddim eto, ysgrifennwch ato o'r ciw cronedig. Ac er ei fod yn brysur, cymerwch yr un rhydd nesaf o'r pwll ac ysgrifennwch ato.

Cyn cyflwyno'r dull hwn o gofnodi data, roedd gennym oddeutu 4K o weithrediadau ysgrifennu, ac yn y modd hwn gwnaethom leihau'r llwyth 4 gwaith. Bellach maent wedi tyfu 6 gwaith arall oherwydd cronfeydd data newydd wedi'u monitro - hyd at 100MB/s. Ac yn awr rydym yn storio logiau am y 3 mis diwethaf mewn cyfaint o tua 10-15TB, gan obeithio y bydd unrhyw ddatblygwr yn gallu datrys unrhyw broblem mewn dim ond tri mis.

Rydym yn deall y problemau

Ond yn syml mae casglu'r holl ddata hwn yn dda, yn ddefnyddiol, yn berthnasol, ond nid yn ddigon - mae angen ei ddeall. Oherwydd mae'r rhain yn filiynau o gynlluniau gwahanol y dydd.

Optimeiddio swmp o ymholiadau PostgreSQL. Kirill Borovikov (Tensor)

Ond mae miliynau yn anhylaw, rhaid inni wneud “llai” yn gyntaf. Ac, yn gyntaf oll, mae angen i chi benderfynu sut y byddwch chi'n trefnu'r peth “llai” hwn.

Rydym wedi nodi tri phwynt allweddol:

  • sy'n anfonwyd y cais hwn
    Hynny yw, o ba raglen y “cyrraedd”: rhyngwyneb gwe, ôl-ben, system dalu neu rywbeth arall.
  • lle digwyddodd
    Ar ba weinydd penodol? Oherwydd os oes gennych chi sawl gweinydd o dan un cymhwysiad, ac yn sydyn mae un yn “mynd yn dwp” (oherwydd bod y “ddisg wedi pydru”, “cof wedi gollwng”, rhyw broblem arall), yna mae angen i chi fynd i'r afael yn benodol â'r gweinydd.
  • как amlygodd y broblem ei hun mewn rhyw ffordd neu'i gilydd

I ddeall “pwy” anfonodd gais atom, rydym yn defnyddio teclyn safonol - gosod newidyn sesiwn: SET application_name = '{bl-host}:{bl-method}'; — rydym yn anfon enw'r gwesteiwr rhesymeg busnes y mae'r cais yn dod ohono, ac enw'r dull neu'r cymhwysiad a'i cychwynnodd.

Ar ôl i ni basio “perchennog” y cais, mae angen ei allbwn i'r log - ar gyfer hyn rydyn ni'n ffurfweddu'r newidyn log_line_prefix = ' %m [%p:%v] [%d] %r %a'. I'r rhai sydd â diddordeb, efallai edrychwch yn y llawlyfrbeth mae'r cyfan yn ei olygu. Mae'n troi allan ein bod ni'n gweld yn y log:

  • amser
  • dynodwyr proses a thrafodion
  • enw cronfa ddata
  • IP y person a anfonodd y cais hwn
  • ac enw dull

Optimeiddio swmp o ymholiadau PostgreSQL. Kirill Borovikov (Tensor)

Yna sylweddolom nad yw'n ddiddorol iawn edrych ar y gydberthynas ar gyfer un cais rhwng gwahanol weinyddion. Nid yn aml mae gennych sefyllfa lle mae un cais yn mynd yn gyfartal yma ac acw. Ond hyd yn oed os yw'r un peth, edrychwch ar unrhyw un o'r gweinyddwyr hyn.

Felly dyma'r toriad "un gweinydd - un diwrnod" trodd allan i fod yn ddigon i ni ar gyfer unrhyw ddadansoddiad.

Mae'r adran ddadansoddol gyntaf yr un peth "sampl" - ffurf gryno o gyflwyno'r cynllun, wedi'i glirio o'r holl ddangosyddion rhifiadol. Yr ail doriad yw'r cais neu'r dull, a'r trydydd toriad yw'r nod cynllun penodol a achosodd broblemau inni.

Pan symudon ni o enghreifftiau penodol i dempledi, cawsom ddwy fantais ar unwaith:

  • gostyngiad lluosog yn nifer y gwrthrychau i'w dadansoddi
    Mae'n rhaid i ni ddadansoddi'r broblem bellach nid yn ôl miloedd o ymholiadau neu gynlluniau, ond yn ôl dwsinau o dempledi.
  • llinell Amser
    Hynny yw, trwy grynhoi'r “ffeithiau” o fewn adran benodol, gallwch chi arddangos eu hymddangosiad yn ystod y dydd. Ac yma gallwch chi ddeall, os oes gennych chi ryw fath o batrwm sy'n digwydd, er enghraifft, unwaith yr awr, ond dylai ddigwydd unwaith y dydd, dylech chi feddwl beth aeth o'i le - pwy achosodd a pham, efallai y dylai fod yma ni ddylai. Mae hwn yn ddull dadansoddi arall nad yw'n rhifiadol, sy'n gwbl weledol.

Optimeiddio swmp o ymholiadau PostgreSQL. Kirill Borovikov (Tensor)

Mae'r dulliau sy'n weddill yn seiliedig ar y dangosyddion rydyn ni'n eu tynnu o'r cynllun: sawl gwaith y digwyddodd patrwm o'r fath, cyfanswm a chyfartaledd yr amser, faint o ddata a ddarllenwyd o'r ddisg, a faint o'r cof...

Oherwydd, er enghraifft, rydych chi'n dod i'r dudalen analytics ar gyfer y gwesteiwr, edrychwch - mae rhywbeth yn dechrau darllen gormod ar y ddisg. Ni all y ddisg ar y gweinydd ei drin - pwy sy'n darllen ohono?

A gallwch chi ddidoli yn ôl unrhyw golofn a phenderfynu beth fyddwch chi'n delio ag ef ar hyn o bryd - y llwyth ar y prosesydd neu'r ddisg, neu gyfanswm nifer y ceisiadau... Fe wnaethon ni ei ddidoli, edrych ar y rhai “uchaf”, ei drwsio a cyflwyno fersiwn newydd o'r cais.
[darlith fideo]

Ac ar unwaith gallwch weld gwahanol gymwysiadau sy'n dod gyda'r un templed o gais fel SELECT * FROM users WHERE login = 'Vasya'. Frontend, backend, prosesu... A ydych yn meddwl tybed pam y byddai prosesu yn darllen y defnyddiwr os nad yw'n rhyngweithio ag ef.

Y ffordd arall yw gweld yn syth o'r cais beth mae'n ei wneud. Er enghraifft, y blaen yw hwn, hwn, hwn, a hyn unwaith yr awr (mae'r llinell amser yn helpu). Ac mae'r cwestiwn yn codi ar unwaith: mae'n ymddangos nad gwaith y blaenwr yw gwneud rhywbeth unwaith yr awr ...

Optimeiddio swmp o ymholiadau PostgreSQL. Kirill Borovikov (Tensor)

Ar ôl peth amser, sylweddolon ni nad oedd gennym ni gydgrynhoad ystadegau yn ôl nodau cynllun. Fe wnaethom ynysu oddi wrth y cynlluniau dim ond y nodau hynny sy'n gwneud rhywbeth gyda data'r tablau eu hunain (darllen / ysgrifennu yn ôl mynegai ai peidio). Mewn gwirionedd, dim ond un agwedd sy'n cael ei hychwanegu o gymharu â'r darlun blaenorol - faint o gofnodion ddaeth â'r nod hwn i ni?, a faint gafodd eu taflu (Rows Removed by Filter).

Nid oes gennych fynegai addas ar y plât, rydych chi'n gwneud cais iddo, mae'n hedfan heibio'r mynegai, yn disgyn i Seq Scan ... rydych chi wedi hidlo'r holl gofnodion ac eithrio un. Pam mae angen 100M o gofnodion wedi'u hidlo arnoch chi bob dydd? Onid yw'n well rholio'r mynegai i fyny?

Optimeiddio swmp o ymholiadau PostgreSQL. Kirill Borovikov (Tensor)

Ar ôl dadansoddi'r holl gynlluniau fesul nod, sylweddolom fod rhai strwythurau nodweddiadol yn y cynlluniau sy'n debygol iawn o edrych yn amheus. A byddai'n braf dweud wrth y datblygwr: "Ffrind, dyma chi ddarllen yn gyntaf yn ôl mynegai, yna didoli, ac yna torri i ffwrdd" - fel rheol, mae un cofnod.

Mae'n debyg bod pawb a ysgrifennodd ymholiadau wedi dod ar draws y patrwm hwn: “Rhowch yr archeb olaf i mi ar gyfer Vasya, ei ddyddiad.” Ac os nad oes gennych fynegai yn ôl dyddiad, neu os nad oes dyddiad yn y mynegai a ddefnyddiwyd gennych, yna byddwch yn camwch ar yr un “rhac” yn union.

Ond rydyn ni'n gwybod mai “rhac” yw hwn - felly beth am ddweud wrth y datblygwr ar unwaith beth ddylai ei wneud. Yn unol â hynny, wrth agor cynllun nawr, mae ein datblygwr yn gweld llun hardd gydag awgrymiadau ar unwaith, lle maen nhw'n dweud wrtho ar unwaith: "Mae gennych chi broblemau yma ac acw, ond maen nhw'n cael eu datrys fel hyn ac felly."

O ganlyniad, mae faint o brofiad oedd ei angen i ddatrys problemau ar y dechrau ac yn awr wedi gostwng yn sylweddol. Dyma'r math o offeryn sydd gennym ni.

Optimeiddio swmp o ymholiadau PostgreSQL. Kirill Borovikov (Tensor)

Ffynhonnell: hab.com

Ychwanegu sylw