PostgreSQL-də sublight üzərində yazırıq: 1 host, 1 gün, 1TB

Bu yaxınlarda standart reseptlərdən istifadə edərək necə dedim SQL oxu sorğularının performansını artırmaq PostgreSQL verilənlər bazasından. Bu gün biz necə danışacağıq qeyd daha səmərəli həyata keçirilə bilər konfiqurasiyada heç bir “twist” istifadə etmədən verilənlər bazasında - sadəcə məlumat axınını düzgün təşkil etməklə.

PostgreSQL-də sublight üzərində yazırıq: 1 host, 1 gün, 1TB

#1. Bölmə

Necə və niyə təşkil etməyə dəyər olduğuna dair bir məqalə "nəzəri olaraq" tətbiqi bölmə artıq olmuşdur, burada biz öz daxilində bəzi yanaşmaların tətbiqi praktikasından danışacağıq yüzlərlə PostgreSQL serveri üçün monitorinq xidməti.

"Geçmiş günlər..."

Əvvəlcə, hər hansı bir MVP kimi, layihəmiz də kifayət qədər yüngül yük altında başladı - monitorinq yalnız on ən kritik server üçün həyata keçirildi, bütün cədvəllər nisbətən yığcam idi... Lakin zaman keçdikcə monitorinq edilən hostların sayı getdikcə artdı. , və bir daha onlardan biri ilə nəsə etməyə çalışdıq 1.5 TB ölçüsündə masalar, anladıq ki, belə yaşamağa davam etmək mümkün olsa da, çox əlverişsizdir.

Dövrlər demək olar ki, epik dövrlərə bənzəyirdi, PostgreSQL 9.x-in müxtəlif versiyaları aktual idi, buna görə də bütün bölmələr "əl ilə" aparılmalı idi. cədvəlin mirası və tetikleyiciler dinamik ilə marşrutlaşdırma EXECUTE.

PostgreSQL-də sublight üzərində yazırıq: 1 host, 1 gün, 1TB
Nəticədə həll o qədər universal oldu ki, bütün cədvəllərə tərcümə oluna bilsin:

  • Hamısını təsvir edən boş "başlıq" ana cədvəli elan edildi zəruri göstəricilər və tetikler.
  • Müştərinin nöqteyi-nəzərindən qeyd “kök” cədvəlində və daxili istifadə ilə aparılmışdır marşrutlaşdırma tetikleyicisi BEFORE INSERT qeyd tələb olunan bölməyə “fiziki olaraq” daxil edilmişdir. Hələ belə bir şey yox idisə, biz bir istisna tutduq və...
  • … istifadə etməklə CREATE TABLE ... (LIKE ... INCLUDING ...) ana cədvəlin şablonu əsasında yaradılmışdır istədiyiniz tarixə məhdudiyyət qoyulmuş bölməbelə ki, məlumatlar əldə edildikdə oxu yalnız onda həyata keçirilir.

PG10: ilk cəhd

Lakin miras yolu ilə bölmə tarixən aktiv yazma axını və ya çoxlu sayda uşaq bölmələri ilə işləmək üçün uyğun olmayıb. Məsələn, tələb olunan bölməni seçmək üçün alqoritmin olduğunu xatırlaya bilərsiniz kvadratik mürəkkəblik, 100+ bölmə ilə işlədiyini, özünüz necə başa düşürsünüz...

PG10-da bu vəziyyət dəstəyi həyata keçirməklə çox optimallaşdırıldı yerli bölmə. Buna görə anbarı köçürdükdən dərhal sonra dərhal tətbiq etməyə çalışdıq, lakin...

Təlimatı araşdırdıqdan sonra məlum oldu ki, bu versiyada yerli olaraq bölünmüş cədvəl:

  • indeks təsvirlərini dəstəkləmir
  • üzərindəki tətikləri dəstəkləmir
  • heç kimin “nəsli” ola bilməz
  • dəstəkləməyin INSERT ... ON CONFLICT
  • bölməni avtomatik yarada bilməz

Dırmıq ilə alnına ağrılı bir zərbə aldıqdan sonra tətbiqi dəyişdirmədən bunu etməyin mümkün olmadığını başa düşdük və sonrakı araşdırmaları altı aya təxirə saldıq.

PG10: ikinci şans

Beləliklə, ortaya çıxan problemləri bir-bir həll etməyə başladıq:

  1. Çünki tetikler və ON CONFLICT Biz onlara hələ də burada və orada ehtiyacımız olduğunu gördük, buna görə də onları işləmək üçün aralıq mərhələ etdik proxy cədvəli.
  2. "marşrutlaşdırma" dan xilas oldum tetikleyicilerde - yəni EXECUTE.
  3. Ayrı-ayrılıqda çıxarıblar bütün indeksləri olan şablon cədvəlibelə ki, onlar hətta proxy cədvəlində mövcud deyillər.

PostgreSQL-də sublight üzərində yazırıq: 1 host, 1 gün, 1TB
Nəhayət, bütün bunlardan sonra biz əsas cədvəli yerli olaraq böldük. Yeni bölmənin yaradılması hələ də tətbiqin vicdanına qalıb.

"mişar" lüğətləri

İstənilən analitik sistemdə olduğu kimi, bizdə də var idi "faktlar" və "kəsiklər" (lüğətlər). Bizim vəziyyətimizdə, bu vəzifədə, məsələn, şablon gövdəsi oxşar yavaş sorğular və ya sorğunun mətni.

"Faktlar" artıq uzun müddətdir ki, gündən-günə bölünürdü, buna görə də köhnəlmiş bölmələri sakitcə sildik və onlar bizi narahat etmədi (loglar!). Amma lüğətlərdə problem var idi...

Onların çox olduğunu söyləməyək, amma təxminən 100 TB "fakt" 2.5 TB lüğət ilə nəticələndi. Belə bir cədvəldən heç bir şeyi rahatlıqla silə bilməzsiniz, onu lazımi vaxtda sıxışdıra bilməzsiniz və ona yazmaq getdikcə yavaşladı.

Lüğət kimi... orada hər giriş düz bir dəfə təqdim edilməlidir... və bu düzgündür, amma!.. Bizə heç kim mane olmur. hər gün üçün ayrıca lüğət! Bəli, bu müəyyən bir artıqlıq gətirir, lakin imkan verir:

  • daha sürətli yaz/oxu daha kiçik bölmə ölçüsünə görə
  • daha az yaddaş istehlak edir daha yığcam indekslərlə işləməklə
  • daha az məlumat saxlamaq köhnəlmişləri tez aradan qaldırmaq qabiliyyətinə görə

Bütün kompleks tədbirlər nəticəsində CPU yükü ~30%, disk yükü ~50% azalıb:

PostgreSQL-də sublight üzərində yazırıq: 1 host, 1 gün, 1TB
Eyni zamanda, biz daha az yüklə verilənlər bazasına tam olaraq eyni şeyi yazmağa davam etdik.

#2. Verilənlər bazasının təkamülü və refaktorinqi

Beləliklə, əlimizdə olanlara qərar verdik hər günün öz bölməsi var data ilə. Əslində, CHECK (dt = '2018-10-12'::date) — və bölmə açarı və qeydin müəyyən bir bölməyə düşməsi şərti var.

Xidmətimizdəki bütün hesabatlar müəyyən bir tarix kontekstində qurulduğundan, "bölünməmiş vaxtlardan" bəri onlar üçün indekslər bütün növlər olmuşdur. (Server, Tarix, Plan Şablonu), (Server, Tarix, Plan node), (Tarix, Xəta sinfi, Server)...

Amma indi hər bölmədə yaşayırlar nüsxələriniz hər bir belə indeks... Və hər bölmə daxilində tarix sabitdir... Belə çıxır ki, indi biz hər bir belə indeksdəyik sadəcə bir sabit daxil edin həm həcmini, həm də onun üçün axtarış vaxtını artıran, lakin heç bir nəticə verməyən sahələrdən biri kimi. Dırmığı özlərinə buraxdılar, ay...

PostgreSQL-də sublight üzərində yazırıq: 1 host, 1 gün, 1TB
Optimallaşdırma istiqaməti aydındır - sadədir tarix sahəsini bütün indekslərdən çıxarın bölünmüş masalarda. Həcmimizi nəzərə alsaq, qazanc təxminəndir 1TB/həftə!

İndi qeyd edək ki, bu terabayt hələ də hansısa yolla qeydə alınmalı idi. Yəni biz də disk indi daha az yüklənməlidir! Bu şəkil bir həftə həsr etdiyimiz təmizlikdən əldə edilən effekti aydın şəkildə göstərir:

PostgreSQL-də sublight üzərində yazırıq: 1 host, 1 gün, 1TB

#3. Pik yükün "yayılması"

Yüklənmiş sistemlərin ən böyük problemlərindən biri də budur lazımsız sinxronizasiya tələb etməyən bəzi əməliyyatlar. Bəzən “diqqət etmədikləri üçün”, bəzən “belə daha asan idi”, amma gec-tez ondan qurtulmalısan.

Gəlin əvvəlki şəkli böyüdək və görək diskimiz var İkiqat amplituda ilə yük altında "nasoslar" bitişik nümunələr arasında, belə bir sıra əməliyyatlarla aydın şəkildə "statistik olaraq" baş verməməlidir:

PostgreSQL-də sublight üzərində yazırıq: 1 host, 1 gün, 1TB

Buna nail olmaq olduqca asandır. Artıq monitorinqlərə başlamışıq təxminən 1000 server, hər biri ayrıca bir məntiqi ip tərəfindən işlənir və hər bir ip müəyyən bir tezlikdə verilənlər bazasına göndəriləcək yığılmış məlumatı sıfırlayır, buna bənzər bir şey:

setInterval(sendToDB, interval)

Burada problem məhz ondadır bütün mövzular təxminən eyni vaxtda başlayır, buna görə də onların göndərilmə vaxtları demək olar ki, həmişə "nöqtəsinə" uyğun gəlir. Vay #2...

Xoşbəxtlikdən, bunu düzəltmək olduqca asandır, "təsadüfi" bir qaçış əlavə edin vaxta görə:

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

#4. Bizə lazım olanı yaddaşda saxlayırıq

Üçüncü ənənəvi yüklənmə problemidir önbellek yoxdur o haradadır bilərdi olmaq.

Məsələn, plan qovşaqları baxımından təhlil etməyə imkan verdik (bütün bunlar Seq Scan on users), amma dərhal fikirləşin ki, onlar əksər hallarda eynidirlər - unutdular.

Xeyr, əlbəttə ki, verilənlər bazasına yenidən heç bir şey yazılmır, bu, tətiyi kəsir INSERT ... ON CONFLICT DO NOTHING. Lakin bu məlumatlar hələ də verilənlər bazasına çatır və bu, lazımsızdır ziddiyyəti yoxlamaq üçün oxuyun etməli. Vay #3...

Keşləmə işə salınmazdan əvvəl/sonra verilənlər bazasına göndərilən qeydlərin sayındakı fərq göz qabağındadır:

PostgreSQL-də sublight üzərində yazırıq: 1 host, 1 gün, 1TB

Bu saxlama yükünün müşayiət olunan azalmasıdır:

PostgreSQL-də sublight üzərində yazırıq: 1 host, 1 gün, 1TB

Ümumi

“Gündə terabayt” sadəcə qorxulu səslənir. Əgər hər şeyi düzgün etsəniz, deməli bu sadəcə 2^40 bayt / 86400 saniyə = ~12.5MB/ski, hətta masa üstü IDE vintlər keçirilir. 🙂

Ancaq ciddi şəkildə, gün ərzində yükün on qat "çarpması" ilə belə, müasir SSD-lərin imkanlarını asanlıqla qarşılaya bilərsiniz.

PostgreSQL-də sublight üzərində yazırıq: 1 host, 1 gün, 1TB

Mənbə: www.habr.com

Добавить комментарий