Ottimisazione di massa di e dumande PostgreSQL. Kirill Borovikov (tensor)

U rapportu presenta alcuni approcci chì permettenu monitorà u rendiment di e dumande SQL quandu ci sò milioni di elli per ghjornu, è ci sò centinaie di servitori PostgreSQL cuntrullati.

Chì suluzioni tecniche ci permettenu di processà in modu efficiente un tali volumi d'infurmazioni, è cumu rende a vita più faciule per un sviluppatore ordinariu.


Quale hè interessatu analisi di prublemi specifichi è diverse tecniche di ottimisazione Queries SQL è risolve i travaglii tipici di DBA in PostgreSQL - pudete ancu vede serie di articuli nantu à stu tema.

Ottimisazione di massa di e dumande PostgreSQL. Kirill Borovikov (tensor)
Mi chjamu Kirill Borovikov, mi rapprisentanu Cumpagnia "Tensor".. In particulare, sò specializatu in u travagliu cù basa di dati in a nostra cumpagnia.

Oghje vi dicu cumu simu impegnati in l'ottimisazione di e dumande, quandu ùn avete micca bisognu di "coglie" u rendiment di una sola dumanda, ma risolve u prublema in massa. Quandu ci sò milioni di dumande, è avete bisognu di truvà avvicinamenti per risolve stu grande prublema.

In generale, "Tensor" per un milione di i nostri clienti hè VLSI - a nostra applicazione: rete suciale corporativa, suluzioni per a cumunicazione video, per a gestione di documenti interni è esterni, sistemi di cuntabilità per a cuntabilità è u magazzinu, ... Hè cusì una "megacombine" per a gestione integrata di l'imprese, in quale ci sò più di 100 prughjetti interni diffirenti. .

Per tutti di travaglià è di sviluppà nurmale, avemu 10 centri di sviluppu in tuttu u paese, anu più 1000 sviluppatori.

Avemu travagliatu cù PostgreSQL da u 2008 è avemu accumulatu una grande quantità di ciò chì processemu - questi sò dati di u cliente, statistiche, analitiche, dati da sistemi d'informazione esterni - più di 400 TB. Solu "in pruduzzione" ci sò circa 250 servitori, è in totale ci sò circa 1000 servitori di basa di dati chì monitoremu.

Ottimisazione di massa di e dumande PostgreSQL. Kirill Borovikov (tensor)

SQL hè una lingua dichjarativa. Discrivi micca "cumu" qualcosa deve travaglià, ma "chì" vulete ottene. U DBMS sapi megliu cumu fà un JOIN - cumu cunnetta i vostri tavulini, quali cundizioni impone, ciò chì passerà per l'indici, ciò chì ùn ...

Certi DBMS accettanu suggerimenti: "No, unisce à sti dui tavule in una tale fila", ma PostgreSQL ùn sapi micca cumu. Questa hè a pusizioni cuscente di i sviluppatori principali: "Hè megliu finisce l'ottimisatore di query chì permette à i sviluppatori di utilizà qualchì tipu di suggerimenti".

Ma, malgradu u fattu chì PostgreSQL ùn permette micca "fora" di gestisce stessu, permette perfettamente vede ciò chì passa ind'èquandu eseguite a vostra dumanda è induve hà prublemi.

Ottimisazione di massa di e dumande PostgreSQL. Kirill Borovikov (tensor)

In generale, cù quali prublemi classici vene un sviluppatore [à DBA]? "Eccu avemu cumpiitu a dumanda, è simu lenti, tuttu hè impiccatu, qualcosa si passa... Qualchì guai !

I mutivi sò quasi sempre listessi:

  • un algoritmu di dumanda inefficace
    U sviluppatore: "Ora aghju 10 tabelle in SQL per ellu attraversu JOIN ..." - è aspetta chì e so cundizioni miraculosamente "svintate" in modu efficace, è uttene tuttu rapidamente. Ma i miraculi ùn succede micca, è ogni sistema cù una tale variabilità (10 tables in one FROM) sempre dà qualchì tipu d'errore. [un articulu]
  • statistiche obsolete
    U mumentu hè assai pertinenti specificamente per PostgreSQL, quandu avete "versu" un grande dataset nantu à u servitore, fate una dumanda - è vi "scans" in u pianu. Perchè eri cuntene 10 records, è oghje ci sò 10 milioni, ma PostgreSQL ùn hè ancu cunuscenza di questu, è deve esse dumandatu. [un articulu]
  • "plugging" in risorse
    Mettite una basa di dati grande è pisanti in un servitore debule chì ùn hà micca abbastanza discu, memoria, o prestazioni di u processatore stessu. È questu hè tuttu ... In qualchì locu ci hè un tettu di rendiment, sopra à quale ùn pudete più saltà.
  • bluccamentu
    Un momentu difficiule, ma sò più pertinenti per diverse dumande di mudificazione (INSERT, UPDATE, DELETE) - questu hè un grande tema separatu.

Pigliate un pianu

... È per tuttu u restu, noi bisognu di un pianu! Avemu bisognu di vede ciò chì succede in u servitore.

Ottimisazione di massa di e dumande PostgreSQL. Kirill Borovikov (tensor)

Un pianu d'esekzione di query per PostgreSQL hè un arbulu di l'algoritmu di esecuzione di query in rapprisintazioni testuale. Esattamente l'algoritmu chì hè statu ricunnisciutu cum'è u più efficace in u risultatu di l'analisi da u pianificatore.

Ogni nodu di l'arburu hè una operazione: estrazione di dati da una tavula o indice, custruisce un bitmap, unisce duie tavule, unisce, intersece o esclude selezzione. Eseguisce una dumanda hè un passaghju attraversu i nodi di questu arbre.

Per uttene u pianu di dumanda, a manera più faciule hè di eseguisce a dichjarazione EXPLAIN. Per uttene cù tutti l'attributi veri, vale à dì eseguite una dumanda nantu à a basa - EXPLAIN (ANALYZE, BUFFERS) SELECT ....

U puntu cattivu: quandu l'eseguite, succede "quì è avà", cusì hè adattatu solu per u debugging locale. Se pigliate un servitore assai caricatu chì hè sottu à un forte flussu di cambiamenti di dati, è vede: "Ehi! Quì avemu fattu pianu pianusya dumanda ". Mezz'ora, un'ora fà - mentre stavate currendu è uttene sta dumanda da i logs, purtendu torna à u servitore, tuttu u vostru dataset è statistiche anu cambiatu. Eseguite per debug - è corre veloce! È ùn pudete micca capisce "perchè", perchè era pianu pianu.

Ottimisazione di massa di e dumande PostgreSQL. Kirill Borovikov (tensor)

Per capisce ciò chì era esattamente in u mumentu chì a dumanda hè eseguita nantu à u servitore, e persone intelligenti anu scrittu modulu auto_explain. Hè presente in quasi tutte e distribuzioni PostgreSQL più cumuni, è pò esse simpliciamente attivatu in u schedariu di cunfigurazione.

S'ellu capisce chì una certa dumanda hè in esecuzione più longu di u limitu chì l'avete dettu, face "snapshot" u pianu di sta dumanda è li scrive inseme à u log.

Ottimisazione di massa di e dumande PostgreSQL. Kirill Borovikov (tensor)

Tuttu pare avà bè, andemu à u logu è vedemu quì ... [footcloth of text]. Ma ùn pudemu micca dì nunda di questu, fora di u fattu chì questu hè un pianu eccellente, perchè hà pigliatu 11ms per compie.

Tuttu pare esse bè - ma nunda ùn hè chjaru ciò chì hè veramente accadutu. In più di u tempu generale, ùn vedemu nunda di speciale. Perchè guardà un testu chjaru cusì "brat" hè generalmente adorable.

Ma ancu s'ellu ùn hè micca evidenti, ancu s'ellu hè inconveniente, ci sò più prublemi fundamentali:

  • U node indica somma nantu à e risorse di tuttu u subtree sottu à ellu. Questu hè, hè simplicemente impussibile di sapè quantu tempu hè statu passatu quì specificamente nantu à questu Index Scan - hè impussibile s'ellu ci hè una cundizione nidificata sottu. Avemu da vede dinamicamente s'ellu ci sò "figlioli" è variabili cundiziunali in l'internu, CTE - è sottrae tuttu questu "in a mente".
  • U sicondu puntu: u tempu chì hè indicatu nantu à u node hè tempu di esecuzione di u nodu. Se stu node hè stata eseguita parechje volte per via di, per esempiu, un ciculu à traversu i registri di a tavola, u pianu aumenta u numeru di cicli - ciculi di stu node. Ma u tempu d'esekzione atomicu stessu ferma u listessu in u pianu. Vale à dì, per capiscenu quantu stu node hè statu realizatu in tuttu, unu deve multiplicà unu per l'altru - novu "in a mente".

In tali scenarii, capisce "Quale hè u ligame più debule?" praticamenti irrealisticu. Dunque, ancu i sviluppatori stessi in u "manuale" scrivenu quellu "Capisce u pianu hè un arte da amparà, una sperienza ...".

Ma avemu 1000 sviluppatori, è sta sperienza ùn pò esse trasmessa à ognunu di elli. Eiu, tu, ellu - sanu, ma qualchissia quì - ùn hè più. Forsi ampararà, o forse micca, ma hà bisognu di travaglià avà - è da induve averebbe sta sperienza.

Pianu di visualizazione

Dunque, avemu capitu chì per trattà questi prublemi, avemu bisognu bona visualizazione di u pianu. [articulu]

Ottimisazione di massa di e dumande PostgreSQL. Kirill Borovikov (tensor)

Prima andemu "in u mercatu" - fighjemu in Internet per ciò chì generalmente esiste.

Ma hè risultatu chì ci sò assai pochi di suluzioni relativamente "vive" chì sò più o menu sviluppati - literalmente, una cosa: spiegà.depesz.com di Hubert Lubaczewski. À l'entrata di u campu "alimenta" a rapprisintazioni testu di u pianu, vi mostra una piastra cù dati analizati:

  • tempu di trasfurmazioni di u nodu propiu
  • tempu tutale nantu à tuttu u subtree
  • u numeru di registri chì sò stati recuperati è chì eranu stati statisticamente previsti
  • corpu di u nodu stessu

Inoltre, stu serviziu hà a capacità di sparte un archiviu di ligami. Avete lanciatu u vostru pianu quì è disse: "Ehi, Vasya, eccu un ligame per voi, qualcosa hè sbagliatu quì".

Ottimisazione di massa di e dumande PostgreSQL. Kirill Borovikov (tensor)

Ma ci sò ancu picculi prublemi.

Prima, una grande quantità di "copia-incolla". Pigliate un pezzu di u logu, mette in quì, è torna, è torna.

Siconda, nisuna analisi di a quantità di dati letti - i stessi buffers chì emette EXPLAIN (ANALYZE, BUFFERS), ùn vedemu micca quì. Simplemente ùn sapi micca cumu disassemble, capisce è travaglià cun elli. Quandu leghjite assai dati è capite chì ùn puderebbe micca esse decomponite currettamente in u discu è in a cache in memoria, sta informazione hè assai impurtante.

U terzu puntu negativu hè u sviluppu assai poviru di stu prughjettu. I commits sò assai chjuchi, hè bonu se una volta ogni sei mesi, è u codice hè in Perl.

Ottimisazione di massa di e dumande PostgreSQL. Kirill Borovikov (tensor)

Ma questi sò tutti "lyrics", unu puderia campà in qualchì modu cun questu, ma ci hè una cosa chì ci alluntanò da stu serviziu. Quessi sò l'errore di analisi di l'espressione di a tabella cumuni (CTE) è parechji nodi dinamichi cum'è InitPlan / SubPlan.

Se crede sta stampa, allora avemu u tempu d'esekzione tutale di ogni node individuali hè più grande di u tempu d'esekzione tutale di a dumanda sana. Tuttu hè simplice - u tempu di generazione di stu CTE ùn hè statu sottrattu da u node CTE Scan. Dunque, ùn sapemu più a risposta curretta, quantu tempu a scansione CTE stessu hà pigliatu.

Ottimisazione di massa di e dumande PostgreSQL. Kirill Borovikov (tensor)

Allora avemu capitu chì era ora di scrive u nostru propiu - eura ! Ogni sviluppatore dice: "Avà scriveremu u nostru propiu, serà super faciule!"

Avemu pigliatu una pila tipica per i servizii web: u core in Node.js + Express, tiratu nantu à Bootstrap è D3.js per belli diagrammi. È e nostre aspittà eranu cumplettamente ghjustificate - avemu ricevutu u primu prototipu in 2 settimane:

  • parser di piani persunalizati
    Questu hè, avà pudemu analizà qualsiasi pianu in generale da quelli generati da PostgreSQL.
  • analisi curretta di i nodi dinamichi - CTE Scan, InitPlan, SubPlan
  • analisi di distribuzione di buffers - induve e pagine di dati sò leghjite da a memoria, induve da a cache locale, induve da u discu
  • hà avutu visibilità
    Per ùn "scavà" tuttu in u logu, ma per vede u "ligame più debule" immediatamente in a stampa.

Ottimisazione di massa di e dumande PostgreSQL. Kirill Borovikov (tensor)

Avemu avutu qualcosa cum'è sta stampa - immediatamente cù evidenziazione di sintassi. Ma di solitu i nostri sviluppatori ùn sò più travagliendu cù una rapprisintazioni cumpleta di u pianu, ma cù qualcosa chì hè più corta. Dopu tuttu, avemu digià analizatu tutti i numeri è i ghjittati à a manca è à a diritta, è lasciate solu a prima linea in u mità, chì tipu di node hè: CTE Scan, CTE generation o Seq Scan secondu qualchì piastra.

Questa hè a rapprisintazioni abbreviata chì chjamemu mudellu di pianu.

Ottimisazione di massa di e dumande PostgreSQL. Kirill Borovikov (tensor)

Chì altru saria cunvene? Saria cunvenutu per vede quale parte di u tempu tutale hè distribuitu à quale nodu - è simpricimenti "incollatu" à u latu. grafico pie.

Puntemu à u node è vede - risulta chì Seq Scan hà pigliatu menu di un quartu di u tempu tutale, è a restante 3/4 hè stata presa da CTE Scan. Horror ! Questa hè una piccula nota nantu à a "rate of fire" di CTE Scan, se l'utilizate attivamente in e vostre richieste. Ùn sò micca assai veloci - perdenu ancu à una scansione di tavulinu regulare. [articulu] [articulu]

Ma di solitu tali diagrammi sò più interessanti, più cumplicati, quandu avemu indicatu subitu à un segmentu, è vedemu, per esempiu, chì certi Seq Scan "manghjanu" più di a mità di u tempu. Inoltre, ci era una sorta di Filtru à l'internu, assai dischi sò stati scartati nantu à questu ... Pudete direttamente scaccià sta stampa à u sviluppatore è dì: "Vasya, tuttu hè male quì! Scuprite, fighjate - qualcosa hè sbagliatu!

Ottimisazione di massa di e dumande PostgreSQL. Kirill Borovikov (tensor)

Naturalmente, senza u "rake" ùn puderia micca fà.

U primu chì anu "pizzatu" era u prublema di arrotondamentu. U tempu di u nodu di ogni nodu individuale in u pianu hè indicatu cù una precisione di 1 µs. È quandu u nùmeru di ciculi di node supera, per esempiu, 1000 - dopu à eseguisce, PostgreSQL hà divisu "finu à", allora quandu u calculu in daretu, avemu u tempu tutale "entre 0.95ms è 1.05ms". Quandu u cuntu va à microseconds, ùn hè sempre nunda, ma quandu hè digià à [milli] seconde, avete da piglià sta informazione in contu quandu "untwisting" risorse secondu i nodi di u pianu "chì cunsuma quantu da quale".

Ottimisazione di massa di e dumande PostgreSQL. Kirill Borovikov (tensor)

U sicondu puntu, più cumplicatu, hè a distribuzione di risorse (quelli buffers) trà i nodi dinamichi. Ci hà custatu altre 2 settimane per e prime 4 settimane per u prototipu.

Hè abbastanza faciule per ottene un tali prublema - facemu CTE è suppostamente leghje qualcosa in questu. In fatti, PostgreSQL hè "intelligente" è ùn leghje nunda direttamente quì. Allora pigliamu u primu discu da ellu, è u centu è primu da u stessu CTE à questu.

Ottimisazione di massa di e dumande PostgreSQL. Kirill Borovikov (tensor)

Fighjemu u pianu è capiscenu - stranu, avemu avutu 3 buffers (pagine di dati) "cunsumatu" in Seq Scan, 1 più in CTE Scan, è 2 più in a seconda CTE Scan. Vale à dì, se simpricimenti riassumemu tuttu, avemu 6, ma da a tableta leghjemu solu 3! CTE Scan ùn leghje nunda da ogni locu, ma travaglia direttamente cù a memoria di prucessu. Allora qualcosa hè chjaramente sbagliatu quì!

In fatti, si trova chì quì tutti quelli 3 pagine di dati chì sò stati dumandati da Seq Scan, prima 1 hà dumandatu u 1st CTE Scan, è dopu u 2nd, è altri 2 sò stati letti à questu, questu hè un totale di 3. e pagine sò state lette dati, micca 6.

Ottimisazione di massa di e dumande PostgreSQL. Kirill Borovikov (tensor)

E sta stampa ci hà purtatu à capisce chì l'esekzione di u pianu ùn hè più un arbre, ma solu un tipu di gràficu aciclicu. E avemu avutu qualcosa cum'è questu diagramma per chì capiscenu "qualcosa da induve hè vinutu". Questu hè, quì avemu creatu un CTE da pg_class, è hà dumandatu duie volte, è quasi tuttu u tempu ci hà pigliatu longu u ramu quandu avemu dumandatu a 2a volta. Hè chjaru chì a lettura di l'entrata 101 hè assai più caru cà solu u 1u da a tavula.

Ottimisazione di massa di e dumande PostgreSQL. Kirill Borovikov (tensor)

Avemu pigliatu un fiatu per un pezzu. Disse: "Avà, Neo, sapete kung fu! Avà a nostra sperienza hè ghjustu nantu à u vostru schermu. Avà pudete aduprà ". [articulu]

Cunsulidazione di log

I nostri 1000 sviluppatori anu respiratu un suspiru di sollievu. Ma avemu capitu chì avemu solu centinaie di servitori di "combattimentu", è tuttu questu "copy-paste" da parte di i sviluppatori ùn hè micca in tuttu cunvene. Avemu capitu chì avemu bisognu di cullà noi stessi.

Ottimisazione di massa di e dumande PostgreSQL. Kirill Borovikov (tensor)

In generale, ci hè un modulu regulare chì pò cullà statistiche, ma ancu deve esse attivatu in a cunfigurazione - questu pg_stat_statements modulu. Ma ùn ci cunvene micca.

Prima, assigna à e stesse dumande sottu schemi differenti in a listessa basa di dati diversi QueryIds. Questu hè, se prima fate SET search_path = '01'; SELECT * FROM user LIMIT 1;è tandu SET search_path = '02'; è a listessa dumanda, allora ci saranu diversi registri in e statistiche di stu modulu, è ùn puderaghju micca cullà statistiche generale specificamente in u cuntestu di stu prufilu di dumanda, senza piglià in contu schemi.

U sicondu puntu chì ci hà impeditu di aduprà - mancanza di piani. Questu hè, ùn ci hè micca un pianu, ci hè solu a dumanda stessu. Avemu vistu ciò chì rallenta, ma ùn capisce micca perchè. È quì turnemu à u prublema di un inseme di dati chì cambia rapidamente.

È l'ultimu mumentu - mancanza di "fatti". Questu hè, ùn pudete micca affruntà un esempiu specificu di l'esekzione di a dumanda - ùn esiste micca, ci hè solu statistiche aggregate. Ancu s'ellu hè pussibule di travaglià cù questu, hè solu assai difficiule.

Ottimisazione di massa di e dumande PostgreSQL. Kirill Borovikov (tensor)

Dunque, avemu decisu di luttà contr'à "copy-paste" è cuminciaru à scrive cullettore.

U cullettore si cunnetta via SSH, "tira" una cunnessione sicura à u servitore cù a basa di dati utilizendu un certificatu, è tail -F "Clings" à questu nantu à u schedariu di log. Allora in questa sessione avemu un "specchiu" cumpleta di tuttu u schedariu di log, chì hè generatu da u servitore. A carica nantu à u servitore stessu hè minima, perchè ùn avemu micca analizatu nunda quì, avemu solu riflette u trafficu.

Siccomu avemu digià cuminciatu à scrive l'interfaccia in Node.js, avemu cuntinuatu à scrive u cullettivu nantu à questu. E sta tecnulugia si ghjustificà, perchè hè assai còmuda di utilizà JavaScript per travaglià cù dati di testu ligeramente furmatu, chì hè u logu. È l'infrastruttura Node.js stessu cum'è una piattaforma backend rende faciule è cunvene per travaglià cù cunnessione di rete, è ancu cù qualchì tipu di flussi di dati.

In cunsiquenza, "stendemu" duie cunnessione: u primu, per "ascoltà" u logu stessu è piglià à noi stessu, è u sicondu, per dumandà periodicamente a basa. "Ma in u logu hè vinutu chì a tableta cù oid 123 hè stata bluccata", ma questu ùn significa nunda per u sviluppatore, è saria bellu di dumandà à a basa "Chì hè OID = 123 in ogni modu?" È cusì dumandemu periodicamente à a basa ciò chì ùn sapemu ancu.

Ottimisazione di massa di e dumande PostgreSQL. Kirill Borovikov (tensor)

"Solu una cosa chì avete lasciatu fora, ci hè una spezia d'api simili à l'elefante! .. "Avemu cuminciatu à sviluppà stu sistema quandu vulemu monitorà 10 servitori. U più criticu in a nostra capiscitura, nantu à quale alcuni prublemi sò stati chì eranu difficiuli di trattà. Ma durante u primu trimestre, avemu ricivutu un centu per u monitoraghju - perchè u sistema "hè intrutu", tutti vulianu, hè cunvenutu per tutti.

Tuttu chistu deve esse aghjuntu, u flussu di dati hè grande, attivu. In realtà, ciò chì monitoremu, ciò chì sapemu cumu trattà, l'utilizamu. Avemu ancu aduprà PostgreSQL cum'è un magazzinu di dati. È nunda hè più veloce per "pour" dati in questu chì l'operatore COPY Ancu micca.

Ma solu "pouring" data ùn hè micca esattamente a nostra tecnulugia. Perchè s'è vo avete circa 50k richieste per seconda nantu à centu servitori, allora questu generarà 100-150GB di logs per ghjornu per voi. Dunque, avemu avutu cun cura "cut" a basa.

Prima, avemu fattu spartizione di ghjornu, perchè, in generale, nimu ùn hè interessatu in a correlazione trà i ghjorni. Chì diffarenza face ciò chì avete avutu ieri, se sta sera avete lanciatu una nova versione di l'applicazione - è digià alcune statistiche novi.

Siconda, avemu amparatu (eranu furzati) assai assai veloce per scrive cun COPY. Questu hè, micca solu COPYperchè hè più veloce chè INSERT, è ancu più veloce.

Ottimisazione di massa di e dumande PostgreSQL. Kirill Borovikov (tensor)

U terzu mumentu - aghju avutu rifiutà triggers, rispittivamenti, è da Chjavi Stranieri. Vale à dì, ùn avemu micca integrità referenziale in tuttu. Perchè s'è vo avete una tavula chì hà un paru di FK nantu à questu, è dite in a struttura di basa di dati chì "eccu una entrata di logu riferita da FK, per esempiu, à un gruppu di entrate", allora quandu l'inserite, PostgreSQL. hè lasciatu senza nunda, ma cumu piglià è onestamente eseguisce SELECT 1 FROM master_fk1_table WHERE ... cù l'identificatore chì vo circate di inserisce - solu per verificà chì sta entrata hè presente quì, chì ùn avete micca "rumpite" sta Chjave Straniera cù a vostra inserzione.

Avemu invece di un record in a tavola di destinazione è i so indici, in più di leghje da tutte e tavule à quale si riferisce. È ùn avemu micca bisognu à tuttu - u nostru compitu hè di registrà quant'è pussibule è u più prestu pussibule cù a minima carica. Allora FK - falà!

U puntu dopu hè aggregazione è hashing. Inizialmente, l'avemu implementatu in a basa di dati - dopu tuttu, hè cunvenutu subitu, quandu u record ghjunghje, per fà in un tipu di tableta. "più unu" ghjustu in u trigger. Bonu, cunvene, ma male in u listessu modu - inserisci un registru, ma site obligatu à leghje è scrive qualcosa altru da un altru tavulu. Inoltre, micca solu per leghje è scrive - ancu per fà ogni volta.

Avà imaginate chì avete una tavula in quale basta cuntà u nùmeru di richieste chì anu passatu per un host particulari: +1, +1, +1, ..., +1. E voi, in principiu, ùn avete micca bisognu - hè tuttu pussibule summa in memoria nant'à u cullettore è mandà à a basa in una volta +10.

Iè, in casu di un malfunzionamentu, a vostra integrità logica pò "falla", ma questu hè un casu quasi irrealisticu - perchè avete un servitore normale, hà una bateria in u controller, avete un logu di transazzione, un log in u sistema di schedari ... In generale, ùn vale a pena. Ùn vale a pena a perdita di rendiment chì uttene cù triggers / FK per u costu chì incurre.

U stessu passa per l'hashing. Una certa dumanda vola à voi, calculate un certu identificatore da ellu in a basa di dati, scrivite à a basa di dati è poi dite à tutti. Tuttu hè bè finu à chì à u mumentu di a registrazione una seconda persona vene à voi chì vulete registrà ellu stessu - è avete un bloccu, è questu hè digià male. Dunque, se pudete trasfiriri a generazione di qualchi ID à u cliente (relative à a basa), hè megliu per fà questu.

Era solu perfettu per noi di utilizà MD5 da un testu - una dumanda, un pianu, un mudellu, ... Calculemu nantu à u latu di u cullettivu, è "pour" una ID pronta in a basa di dati. A durata di l'MD5 è a partizione di ogni ghjornu ùn ci permettenu micca di preoccupassi di pussibuli collisioni.

Ottimisazione di massa di e dumande PostgreSQL. Kirill Borovikov (tensor)

Ma per arregistrà tuttu questu rapidamente, avemu bisognu di mudificà a prucedura di registrazione stessu.

Cumu sò generalmente scritti i dati? Avemu un tipu di dataset, u decomponemu in parechje tavule, è dopu COPY - prima in u primu, dopu in u sicondu, in u terzu ... Hè inconveniente, perchè paremu chì scrivemu un flussu di dati in trè passi sequentially. . Dispiacevule. Pò esse fattu più veloce? Pò!

Per fà questu, hè abbastanza solu per decompone sti flussi in parallelu cù l'altri. Ci hè chì avemu sbagliati, dumande, mudelli, chjusi chì volenu in fili separati, ... - è scrivimu tuttu in parallelu. Per questu hè abbastanza mantene un canale COPY permanentemente apertu à ogni tavula di destinazione individuale.

Ottimisazione di massa di e dumande PostgreSQL. Kirill Borovikov (tensor)

Questu hè, u cullettore ci hè sempre un flussu, in quale possu scrive i dati chì aghju bisognu. Ma per chì a basa di dati veda sta dati, è qualcunu ùn hè micca appiccicatu in chjusi, aspittendu chì sta dati sia scritta, COPY deve esse interrotta à certi intervalli. Per noi, u periodu di l'ordine di 100ms hè diventatu u più efficau - l'avemu chjusu è l'apre subitu à a stessa tavola. È s'ellu ùn avemu micca abbastanza d'un flussu à certi picchi, allora facemu un pooling finu à un certu limitu.

Inoltre, avemu scupertu chì per un tali prufilu di carica, ogni aggregazione, quandu i registri sò cullati in pacchetti, hè male. U male classicu hè INSERT ... VALUES è altri 1000 records. Perchè à quellu puntu avete un piccu di scrittura nantu à i media, è tutti l'altri chì pruvate di scrive qualcosa à u discu seranu aspittendu.

Per caccià tali anomalie, basta micca aggregate nunda, ùn buffer à tuttu. È se u buffering à u discu si verifica (per fortuna, l'API Stream in Node.js vi permette di scopre) - pospone sta cunnessione. Hè quandu un avvenimentu vene à voi chì hè liberu di novu - scrivitevi da a fila accumulata. Intantu, hè occupatu - pigliate u prossimu liberu da a piscina è scrivite.

Prima di implementà stu approcciu à scrive dati, avemu avutu circa 4K scrittura ops, è in questu modu avemu riduciutu a carica per 4 volte. Avà sò cresciuti altre 6 volte per via di novi basa di dati monitorati - finu à 100MB / s. È avà guardamu logs per l'ultimi mesi 3 in quantità di circa 10-15TB, sperendu chì ogni sviluppatore pò risolve ogni prublema in trè mesi.

Capemu i prublemi

Ma simpricimenti cullà tutti sti dati hè bonu, utile, apprupriatu, ma micca abbastanza - avete bisognu di capiscenu. Perchè questi sò milioni di piani diffirenti per ghjornu.

Ottimisazione di massa di e dumande PostgreSQL. Kirill Borovikov (tensor)

Ma milioni ùn sò micca cuntrullabili, prima deve fà "più chjucu". E, prima di tuttu, avete bisognu di decide cumu urganizà questu "più chjucu".

Avemu identificatu trè punti chjave per noi stessi:

  • chì mandatu sta dumanda
    Questu hè, da quale applicazione hè "arrivatu": interfaccia web, backend, sistema di pagamentu, o qualcosa altru.
  • induve hè accadutu
    In quale servore specificu. Perchè s'è vo avete parechji servitori sottu una sola applicazione, è di colpu unu "smussatu" (perchè u "discu hè putridu", "memoria fugliata", qualchi altri prublemi), allura vi tocca à specifichi à u servore.
  • quantu u prublema si manifesta in un modu o un altru

Per capiscenu "quale" ci hà mandatu una dumanda, usemu un strumentu regulare - stabilisce una variabile di sessione: SET application_name = '{bl-host}:{bl-method}'; - Mandemu u nome di l'ospite di logica cummerciale da quale vene a dumanda, è u nome di u metudu o l'applicazione chì l'hà iniziatu.

Dopu avè passatu u "maestru" di a dumanda, deve esse affissata in u logu - per questu avemu cunfigurà a variabile log_line_prefix = ' %m [%p:%v] [%d] %r %a'. Per quelli chì sò interessati, forse fighjate in u manualeciò chì tuttu significa. Ci hè chì vedemu in u logu:

  • время
  • ID di prucessu è transazzione
  • nome di basa
  • L'IP di a persona chì hà mandatu sta dumanda
  • è u nome di u metudu

Ottimisazione di massa di e dumande PostgreSQL. Kirill Borovikov (tensor)

In più, avemu capitu chì ùn hè micca assai interessante per guardà a correlazione per una dumanda trà i diversi servitori. Raramente, avete una situazione induve avete una applicazione ugualmente "crap" quì è quì. Ma ancu s'è u listessu - fighjate à qualsiasi di sti servitori.

Allora, tagliate "un servitore - un ghjornu" avemu trovu abbastanza per ogni analisi.

A prima sezione analitica hè a stessa "mostra" - una forma abbreviata di a presentazione di u pianu, liberata da tutti l'indicatori numerichi. U sicondu tagliu hè l'applicazione o u metudu, è u terzu hè u node di u pianu specificu chì ci hà causatu prublemi.

Quandu avemu passatu da istanze concrete à mudelli, avemu dui vantaghji à una volta:

  • riduzzione multiple in u numeru di l'uggetti per l'analisi
    Avemu da analizà u prublema micca più per millaie di dumande o piani, ma da decine di mudelli.
  • timeline
    Questu hè, riassunendu i "fatti" in una certa sezione, si pò vede a so apparenza durante u ghjornu. È quì pudete capisce chì s'ellu avete qualchì mudellu chì succede, per esempiu, una volta à l'ora, ma duverebbe - una volta à ghjornu, duvete pensà à ciò chì hè andatu male - da quale è perchè hè statu chjamatu, forsi si deve esse quì. ùn deve micca. Questu hè un altru modu di analisi non numericu, puramente visuale.

Ottimisazione di massa di e dumande PostgreSQL. Kirill Borovikov (tensor)

I metudi rimanenti sò basati nantu à l'indicatori chì avemu estratto da u pianu: quante volte un tali mudellu hè accadutu, u tempu tutale è mediu, quantu dati sò stati letti da u discu, è quantu da a memoria ...

Perchè, per esempiu, venite à a pagina di analitica di l'ospiti, fighjate - qualcosa hè troppu per leghje nantu à u discu. U discu nantu à u servitore ùn pò micca affruntà - è quale leghje da ellu?

È pudete sorte per ogni culonna è decide ciò chì avete da trattà avà - cù a carica nantu à u processatore o nantu à u discu, o cù u numeru tutale di dumande ... Sorted, fighjatu à i "top", fighjatu. - hà lanciatu una nova versione di l'applicazione.
[video lecture]

È immediatamente pudete vede diverse applicazioni chì vanu cù u stessu mudellu da una dumanda cum'è SELECT * FROM users WHERE login = 'Vasya'. Frontend, backend, processing... È vi dumandate perchè u processu deve leghje l'utilizatore s'ellu ùn interagisce micca cun ellu.

A manera inversa hè da l'applicazione per vede immediatamente ciò chì face. Per esempiu, u frontend hè questu, questu, questu, è questu una volta à l'ora (solu u timeline aiuta). È a quistione hè subitu - pare chì ùn hè micca l'affari di u frontend per fà qualcosa una volta à l'ora ...

Ottimisazione di massa di e dumande PostgreSQL. Kirill Borovikov (tensor)

Dopu qualchì tempu, avemu capitu chì ci mancava un aggregatu statistiche per i nodi di u pianu. Avemu isolatu da i piani solu quelli nodi chì facenu qualcosa cù i dati di e tavule stessu (leghje / scrivite per indice o micca). In fatti, in quantu à a stampa precedente, hè aghjuntu solu un aspettu - quanti dischi ci hà purtatu stu nodu, è quantu hè statu scartatu (File eliminate da u filtru).

Ùn avete micca un indice adattatu nantu à a piastra, fate una dumanda à questu, vola oltre l'indici, casca in u Seq Scan ... avete filtratu tutti i registri eccettu unu. E perchè avete bisognu di 100 milioni di dischi filtrati per ghjornu, ùn hè micca megliu per rinfurzà l'indici?

Ottimisazione di massa di e dumande PostgreSQL. Kirill Borovikov (tensor)

Dopu avè analizatu tutti i piani per i nodi, avemu capitu chì ci sò parechje strutture tipiche in i piani chì più prubabilmente parenu suspetti. È saria bellu di dì à u sviluppatore: "Amicu, quì prima leghje per indice, poi sorte, è dopu tagliatu" - in regula, ci hè una sola entrata.

Tutti quelli chì anu scrittu dumande anu prubabilmente scontru cù un tali mudellu: "Datemi l'ultimu ordine per Vasya, a so data." È se ùn avete micca un indice per data, o ùn ci hè micca una data in l'indici chì avete utilizatu, allora fate un passu. esattamente nantu à un tali "rake".

Ma sapemu chì questu hè un "rake" - allora perchè micca immediatamente dì à u sviluppatore ciò chì deve fà. Dunque, aprendu u pianu avà, u nostru sviluppatore vede immediatamente una bella stampa cù suggerimenti, induve ellu hè subitu dettu: "Avete prublemi quì è quì, ma sò risolti cusì è quellu".

In u risultatu, a quantità di sperienza chì era necessariu per risolve i prublemi à u principiu è avà hè cascatu significativamente. Quì avemu un tali strumentu.

Ottimisazione di massa di e dumande PostgreSQL. Kirill Borovikov (tensor)

Source: www.habr.com

Add a comment