Kami nyerat dina PostgreSQL dina sublight: 1 host, 1 dinten, 1TB

Anyar-anyar ieu kuring nyarioskeun ka anjeun kumaha, nganggo resep standar ningkatkeun kinerja SQL maca queries ti database PostgreSQL. Dinten ieu kami bakal ngobrol ngeunaan kumaha ngarékam bisa dilakukeun leuwih éfisién dina pangkalan data tanpa nganggo "pulas" dina config - cukup ku leres ngatur aliran data.

Kami nyerat dina PostgreSQL dina sublight: 1 host, 1 dinten, 1TB

#1. Bagéan

Hiji artikel ngeunaan kumaha jeung naha éta patut ngatur partisi dilarapkeun "dina téori" geus, didieu urang bakal ngobrol ngeunaan prakték nerapkeun sababaraha pendekatan dina urang jasa ngawaskeun pikeun ratusan server PostgreSQL.

"Hal-hal anu kapungkur..."

Mimitina, sapertos MVP mana waé, proyék kami dimimitian dina beban anu lumayan - ngawaskeun ngan ukur pikeun sapuluh server anu paling kritis, sadaya tabel rélatif kompak ... , sarta sakali deui urang diusahakeun ngalakukeun hiji hal kalawan salah sahiji tabél 1.5TB ukuranana, urang sadar yén sanajan éta bisa neruskeun hirup kawas ieu, éta pisan pikaresepeun.

Waktu éta ampir kawas jaman epik, versi béda tina PostgreSQL 9.x éta relevan, jadi sagala partisi kudu dipigawé "sacara manual" - ngaliwatan warisan tabel sarta micu routing kalawan dinamis EXECUTE.

Kami nyerat dina PostgreSQL dina sublight: 1 host, 1 dinten, 1TB
Solusi anu dihasilkeun tétéla cukup universal anu tiasa ditarjamahkeun kana sadaya tabel:

  • Hiji kosong "header" tabel indungna dinyatakeun, nu digambarkeun sadayana indéks diperlukeun tur micu.
  • Catetan tina sudut pandang klien dilakukeun dina tabel "root", sareng nganggo internal routing pemicu BEFORE INSERT catetan ieu "fisik" diselapkeun kana bagian diperlukeun. Upami teu acan aya anu sapertos kitu, urang mendakan pengecualian sareng ...
  • … ku ngagunakeun CREATE TABLE ... (LIKE ... INCLUDING ...) dijieun dumasar kana citakan tabel indungna bagian kalawan pangwatesan dina tanggal dipikahoyongku kituna lamun data dipulut, bacaan dipigawé ngan di dinya.

PG10: usaha munggaran

Tapi ngabagi warisan sacara sajarahna henteu cocog pikeun ngatur aliran nulis aktip atanapi sajumlah ageung partisi anak. Contona, Anjeun bisa ngelingan yen algoritma pikeun milih bagian diperlukeun tadi pajeulitna kuadrat, yén éta tiasa dianggo sareng 100+ bagian, anjeun nyalira ngartos kumaha...

Dina PG10 kaayaan ieu greatly dioptimalkeun ku ngalaksanakeun rojongan partitioning pribumi. Ku alatan éta, urang langsung nyoba nerapkeun eta langsung saatos migrasi gudang, tapi ...

Sakumaha anu kabuktian saatos ngagali manual, tabel partisi asli dina versi ieu nyaéta:

  • teu ngarojong déskripsi indéks
  • teu ngarojong pemicu dina eta
  • teu tiasa janten "turunan" saha waé
  • teu ngarojong INSERT ... ON CONFLICT
  • teu bisa ngahasilkeun bagian otomatis

Sanggeus narima niup nyeri kana dahi kalawan rake a, urang sadar yén éta bakal mungkin mun ngalakukeun tanpa ngaropéa aplikasi, sarta ditunda panalungtikan salajengna salila genep bulan.

PG10: kasempetan kadua

Janten, urang mimitian ngarengsekeun masalah anu timbul hiji-hiji:

  1. Kusabab micu na ON CONFLICT Kami mendakan yén kami masih peryogi aranjeunna di ditu di dieu, janten kami ngadamel tahap panengah pikeun ngagarap aranjeunna méja proxy.
  2. Ngaleungitkeun "ruteu" dina micu - nyaeta, ti EXECUTE.
  3. Aranjeunna nyandak kaluar nyalira tabel template kalawan sagala indéksambéh maranéhanana henteu malah hadir dina tabel proxy.

Kami nyerat dina PostgreSQL dina sublight: 1 host, 1 dinten, 1TB
Tungtungna, saatos sadayana ieu, urang ngabagi tabel utama sacara asli. Nyiptakeun bagian anyar masih ditinggalkeun ka nurani aplikasi.

Kamus "Sawing".

Sapertos dina sistem analitis naon waé, kami ogé ngagaduhan "fakta" sareng "potongan" (kamus). Dina hal urang, dina kapasitas ieu aranjeunna acted, contona, awak template queries slow sarupa atawa téks query sorangan.

"Fakta" parantos dipisahkeun sadinten kanggo waktos anu lami, janten kami ngahapus bagian anu luntur, sareng aranjeunna henteu ngaganggu kami (log!). Tapi aya masalah sareng kamus ...

Teu disebutkeun yen aya loba di antarana, tapi kira-kira 100TB "fakta" ngahasilkeun kamus 2.5TB. Anjeun teu tiasa ngahapus nanaon tina méja sapertos kitu, anjeun moal tiasa ngompres dina waktos anu cekap, sareng nyerat kana éta laun janten langkung laun.

Siga kamus... di dinya, unggal entri kudu dibere persis sakali ... jeung ieu bener, tapi! kamus misah pikeun unggal poé! Leres, ieu nyababkeun redundansi anu tangtu, tapi ngamungkinkeun:

  • nulis / maca leuwih gancang alatan ukuran bagian leutik
  • meakeun memori kirang ku gawé bareng indéks langkung kompak
  • nyimpen data kirang alatan kamampuhan pikeun gancang nyabut tinggaleun jaman

Salaku hasil tina sakabeh kompléks ukuran Beban CPU turun ku ~30%, beban disk ku ~50%:

Kami nyerat dina PostgreSQL dina sublight: 1 host, 1 dinten, 1TB
Dina waktu nu sarua, urang terus nulis persis hal anu sarua kana database, ngan kalawan beban kirang.

#2. Évolusi database sareng refactoring

Janten urang netepkeun naon anu urang gaduh unggal poé boga bagian sorangan kalawan data. Sabenerna, CHECK (dt = '2018-10-12'::date) - tur aya hiji konci partisi jeung kaayaan pikeun rékaman digolongkeun kana bagian husus.

Kusabab sadaya laporan dina jasa kami diwangun dina kontéks tanggal anu spesifik, indéks pikeun aranjeunna ti saprak "jaman anu henteu dipisahkeun" mangrupikeun sagala jinis. (Server, tanggal, Citakan Rencana), (Server, tanggal, titik rencana), (tanggal, Kelas kasalahan, Server)...

Tapi ayeuna aranjeunna hirup dina unggal bagian salinan Anjeun unggal indéks sapertos ... Sarta dina unggal bagian tanggal nyaéta konstanta... Tétéla ayeuna urang aya dina unggal indéks misalna saukur ngasupkeun konstanta salaku salah sahiji widang, nu ngaronjatkeun duanana volume sarta waktu pilarian pikeun eta, tapi teu mawa hasil nanaon. Aranjeunna ninggalkeun rake sorangan, aduh...

Kami nyerat dina PostgreSQL dina sublight: 1 host, 1 dinten, 1TB
Arah optimasi atra - basajan miceun widang tanggal tina sagala indéks dina tabel partitioned. Dibikeun jilid kami, gain nyaeta ngeunaan 1TB/minggu!

Ayeuna hayu urang perhatikeun yén terabyte ieu masih kedah dirékam kumaha waé. Nyaeta, urang ogé disk ayeuna kedah beban kirang! Gambar ieu jelas nunjukkeun pangaruh anu dicandak tina beberesih, anu kami bakti saminggu:

Kami nyerat dina PostgreSQL dina sublight: 1 host, 1 dinten, 1TB

#3. "Nyebarkeun" beban puncak

Salah sahiji troubles badag sistem dimuat nyaéta sinkronisasi kaleuleuwihan sababaraha operasi anu teu merlukeun eta. Kadang-kadang "kusabab teu aya bewara", sakapeung "éta gampang cara éta", tapi sooner atanapi engké anjeun kudu meunang leupas tina eta.

Hayu urang ngazum gede dina gambar saméméhna tur tingal yen urang boga disk "pompa" handapeun beban kalayan amplitudo ganda antara sampel padeukeut, nu jelas "statistik" teu kudu lumangsung kalawan sababaraha operasi:

Kami nyerat dina PostgreSQL dina sublight: 1 host, 1 dinten, 1TB

Ieu rada gampang pikeun ngahontal. Kami parantos ngamimitian ngawaskeun ampir 1000 server, masing-masing diolah ku benang logis anu misah, sareng unggal benang ngareset inpormasi akumulasi pikeun dikirim ka pangkalan data dina frékuénsi anu tangtu, sapertos kieu:

setInterval(sendToDB, interval)

Masalahna di dieu perenahna persis dina kanyataan yén kabéh threads dimimitian dina waktu nu sarua, jadi waktu ngirimna ampir sok coincide "to the point". Aduh #2...

Untungna, ieu rada gampang pikeun ngalereskeun, nambahkeun hiji "acak" ngajalankeun-up ku waktos:

setInterval(sendToDB, interval * (1 + 0.1 * (Math.random() - 0.5)))

#4. Urang cache naon urang kudu

Masalah highload tradisional katilu nyaéta euweuh cache dimana anjeunna bisa janten.

Salaku conto, kami ngamungkinkeun pikeun nganalisis tina segi titik rencana (sadayana ieu Seq Scan on users), tapi langsung mikir yén aranjeunna, sabagéan ageung, sami - aranjeunna hilap.

Taya, tangtosna, nanaon geus ditulis kana database deui, ieu motong kaluar pemicu kalawan INSERT ... ON CONFLICT DO NOTHING. Tapi data ieu masih ngahontal database, sarta éta teu perlu maca pikeun mariksa konflik kudu ngalakukeun. Aduh #3...

Bédana dina jumlah rékaman anu dikirim ka pangkalan data sateuacan / saatos cache diaktipkeun jelas:

Kami nyerat dina PostgreSQL dina sublight: 1 host, 1 dinten, 1TB

Sareng ieu mangrupikeun turunna beban panyimpenan:

Kami nyerat dina PostgreSQL dina sublight: 1 host, 1 dinten, 1TB

dina total

"Terabyte-per-day" ngan disada pikasieuneun. Upami anjeun ngalakukeun sadayana leres, maka éta waé 2^40 bait / 86400 detik = ~12.5MB/séta malah screws IDE desktop dicekel. 🙂

Tapi serius, sanajan kalawan sapuluh kali "skew" beban salila poé, anjeun bisa kalayan gampang minuhan kamampuhan SSDs modern.

Kami nyerat dina PostgreSQL dina sublight: 1 host, 1 dinten, 1TB

sumber: www.habr.com

Tambahkeun komentar