Incidentu reaģēšana

ClickHouse "Too many parts": kāpēc datu ievietošana neizdodas un kā to novērst

Ievietošana palēninās un tad izgāžas ar "Too many parts. Merges are processing significantly slower than inserts". Limita palielināšana ir kārdinošs un nepareizs risinājums. Lūk, kas patiesībā notiek un kā datu plūsmu atkal padarīt veselīgu.

· 11 min lasīšanai · AG Data komanda

ClickHouse "Too many parts" parasti parādās dienā, kad viss pārējais izskatās normāli. Ievietošana sāk aizņemt ilgāku laiku, tad datu plūsma sāk izgāzties ar Too many parts (N). Merges are processing significantly slower than inserts, un dati sāk krāties rindās vai pazust. Kļūdas ziņojums ir godīgs: ClickHouse rada datu daļas ātrāk, nekā spēj tās apvienot. Risinājums gandrīz nekad nav limita palielināšana. Tas ir radīt mazāk daļu.

Kā darbojas daļas un apvienošana

Katrs INSERT MergeTree tabulā ieraksta vismaz vienu jaunu daļu (part): direktoriju ar sakārtotiem, saspiestiem kolonnu failiem diskā. ClickHouse neatjaunina lielu failu uz vietas. Tā vietā fona apvienošana (merge) pastāvīgi apvieno mazas daļas lielākās. Tieši tas padara ievietošanu ātru un vaicājumus efektīvus, kamēr apvienošana tiek līdzi.

Šai kļūdai svarīgas divas detaļas:

Materializētie skati to pastiprina. Katra ievietošana avota tabulā ievieto datus arī katra skata mērķa tabulā, tāpēc arī katrā mērķa tabulā rodas jaunas daļas.

Limiti aiz kļūdas

ClickHouse sevi aizsargā ar MergeTree iestatījumiem, kas reaģē uz aktīvo daļu skaitu:

Aizkaves fāze ir jūsu agrīnais brīdinājums. Ja ievietošana dienām ilgi kļuvusi lēnāka, bieži iemesls ir tieši šis.

1. solis: atrodiet, kur ir daļas

Sāciet ar aktīvajām daļām katrā nodalījumā, kā iesaka ClickHouse problēmu novēršanas ceļvedis:

SELECT database, table, partition_id,
       count() AS active_parts,
       formatReadableSize(sum(bytes_on_disk)) AS size,
       formatReadableSize(avg(bytes_on_disk)) AS avg_part
FROM system.parts
WHERE active
GROUP BY database, table, partition_id
ORDER BY active_parts DESC
LIMIT 20;

Lasiet rezultātu, paturot prātā trīs jautājumus:

  1. Viens nodalījums ar tūkstošiem mazu daļu? Kaut kas tajā raksta mazas, biežas ievietošanas. To atklāj vidējais daļas izmērs dažu kilobaitu vai megabaitu apmērā.
  2. Tūkstošiem nodalījumu ar dažām daļām katrā? Nodalījumu atslēga ir pārāk sīka, piemēram, pa lietotājiem, ierīcēm vai stundām uz gadiem datu. Jūs tuvojaties max_parts_in_total, un cieš arī vaicājumi.
  3. Daļas ir normāla izmēra, bet tik un tā krājas? Ievietošana var būt kārtībā, un problēma ir apvienošanā.

2. solis: pārbaudiet, vai apvienošana tiešām notiek

SELECT database, table, round(elapsed) AS sec,
       round(progress * 100) AS pct, num_parts,
       formatReadableSize(total_size_bytes_compressed) AS size
FROM system.merges
ORDER BY elapsed DESC;

Ja apvienošana notiek, bet lēni, skatieties uz serveri: diska caurlaidību, brīvo vietu diskā (apvienošanai vajag vietu jaunās daļas ierakstīšanai, pirms vecās tiek dzēstas), CPU un konkurējošu fona darbu, piemēram, mutācijas. Ja nekas netiek apvienots vispār, pārbaudiet servera žurnālā apvienošanas kļūdas un to, vai kāds apkopes laikā neizpildīja SYSTEM STOP MERGES un nekad neizpildīja SYSTEM START MERGES.

3. solis: pārtrauciet radīt tik daudz daļu

Šis ir īstais risinājums, un parasti tas ir lietotnes pusē.

Grupējiet ievietošanas. ClickHouse iesaka paketes ar vismaz 1000 rindām, ideāli 10 000 līdz 100 000, un aptuveni vienu ievietošanas vaicājumu sekundē uz tabulu. Serviss, kas sūta vienu rindu katrā HTTP pieprasījumā no piecdesmit podiem, var radīt tūkstošiem daļu minūtē. Buferējiet lietotnē, rindas patērētājā vai datu ielādes rīkā un izlādējiet pēc izmēra vai laika.

Izmantojiet asinhrono ievietošanu, ja grupēšana klientā nav praktiska. Ar async_insert = 1 serveris savāc mazas ievietošanas buferī un ieraksta tās kā vienu daļu, kad buferis sasniedz izmēra, laika vai vaicājumu skaita slieksni:

INSERT INTO events
SETTINGS async_insert = 1, wait_for_async_insert = 1
VALUES (...);

Paturiet wait_for_async_insert = 1, kas ir noklusējums. Tad klients saņem apstiprinājumu tikai pēc tam, kad dati ir ierakstīti. Vērtība 0 padara ievietošanu par "aizsūti un aizmirsti", un ClickHouse dokumentācija to sauc par ļoti riskantu, jo klients var nekad neuzzināt, ka ievietošana neizdevās.

Salabojiet nodalījumu atslēgu. Nodalījumi ir datu pārvaldības rīks, nevis indekss. Mēneša nodalījums pēc datuma kolonnas ir klasiska izvēle; dienas nodalījums var būt jēgpilns lielam apjomam ar īsu glabāšanas laiku. Nodalīšana pēc lietotāja ID, klienta ID vai jebkā ar tūkstošiem vērtību vairo daļas un neļauj apvienošanai darīt savu darbu. Nodalījumu atslēgas maiņa nozīmē jaunas tabulas izveidi un datu pārvietošanu, tāpēc izvēlieties pareizi jau sākumā. Mēs to pieminējām, aprakstot, kā veidojam ClickHouse datu noliktavas no mantotiem datiem.

parts_to_throw_insert palielināšana uz laiku liks kļūdai pazust, un īstā ārkārtas situācijā īslaicīgs palielinājums var uzturēt datu plūsmu, kamēr salabojat avotu. Taču ClickHouse ceļvedis skaidri saka, ka tas nav risinājums: vairāk daļu nozīmē vairāk failu un metadatu, lēnākus vaicājumus, un tā pati siena atgriežas vēlāk, augstāka un grūtāk pārvarama. Ja to palielināt, pierakstiet, kad un kāpēc, un atjaunojiet vērtību, kad daļu skaits ir normāls.

Kā izkļūt no bedres

Kad mazo daļu avots ir novērsts, apvienošana parasti panāk pati. Sekojiet aktīvo daļu skaitam no 1. soļa: tam vajadzētu nostabilizēties un tad kristies. Vienam stipri sadrumstalotam nodalījumam var piespiest apvienošanu ar OPTIMIZE TABLE ... PARTITION ..., taču lielai tabulai tas ir smags darbs, tāpēc izpildiet to ārpus maksimālās slodzes stundām, vienu nodalījumu vienlaikus, un izvairieties no FINAL uz veselām lielām tabulām. Pirms sākat, pārliecinieties, ka diskā ir pietiekami brīvas vietas.

Dati, kurus incidenta laikā neizdevās ievietot, ir cits jautājums. Ja jūsu datu avoti neatkārto mēģinājumus vai rindas glabāšanas laiks ir īsāks par dīkstāvi, daļa datu ir zaudēta. Pārbaudiet, ko jūsu plūsma dara ar neizdevušos ievietošanu, pirms nākamā incidenta, nevis tā laikā.

Uzraugiet to, pirms tas salūzt

  1. Maksimālais aktīvo daļu skaits nodalījumā katrai tabulai, ar brīdinājumu krietni zem parts_to_delay_insert.
  2. Kopējais aktīvo daļu skaits tabulā salīdzinājumā ar max_parts_in_total.
  3. Ievietošanas latentums un kļūdas jūsu datu plūsmā.
  4. Notiekošo apvienošanu skaits un ilgums, kā arī brīvā vieta datu sējumā.

Šie rādītāji pieder tajā pašā panelī, kur pārējie rādītāji, kas prognozē datubāzes incidentus. Lēns daļu skaita pieaugums ir redzams dienām ilgi pirms pirmās neizdevušās ievietošanas.

Galvenās atziņas

ClickHouse MergeTree Datu ievietošana Incidentu reaģēšana
Sadarbība ar mums

ClickHouse atraida datu ievietošanu?

Mēs atrodam, kas pārpludina jūsu ClickHouse tabulas ar daļām, salabojam ievietošanas plūsmu un nodalīšanu un ieviešam monitoringu, kas brīdina laikus. Pirmā reakcija uz kritiskiem incidentiem 15 minūšu laikā, 24/7.

Sazināties Vairāk no emuāra