Kad jādzēš rindas ClickHouse, SQL izskatās pazīstams, bet dzinējs zem tā nav. MergeTree tabulas glabā datus nemainīgās daļās, tāpēc "dzēšana" vai nu paslēpj rindas un gaida, kamēr sapludināšana tās iztīrīs, vai pārraksta veselas daļas uz diska. Mazā tabulā atšķirību gandrīz nemana. Tabulā ar miljardiem rindu izvēle nosaka, vai dzēšana beidzas sekundēs, ilgst dienu vai iestrēgst un bloķē katru nākamo izmaiņu.
Trīs dzēšanas veidi, no lētākā līdz dārgākajam
- Dzēst veselas particijas (vai izpildīt
TRUNCATEtabulai), ja dzēšamie dati sakrīt ar particiju atslēgu. Tas izņem daļas kā failus, neko nepārrakstot. - Vieglais
DELETE FROMmērķtiecīgai dzēšanai. Tas atzīmē rindas kā dzēstas un ļauj vēlākām sapludināšanām tās izņemt. ALTER TABLE ... DELETE, klasiska mutācija, kas pārraksta katru daļu ar atbilstošām rindām.
Pati DELETE dokumentācija norāda uz pirmo variantu: biežai lielapjoma dzēšanai tabulā ar piemērotu particiju atslēgu ALTER TABLE ... DROP PARTITION ir ātrāks.
Vieglais DELETE: kas notiek patiesībā
-- vieglā dzēšana: atzīmē rindas, fiziski tās izņem vēlākas sapludināšanas
DELETE FROM events WHERE user_id = 42;
-- ierobežojiet ar vienu particiju (nereplicētam MergeTree jānorāda tieši)
DELETE FROM events IN PARTITION '202611' WHERE user_id = 42;
Vieglais DELETE joprojām ir mutācija, bet lēta. ClickHouse skartajām daļām pievieno slēptu kolonnu _row_exists un izpilda dzēšanu kā šīs kolonnas atjaunināšanu uz 0. SELECT vaicājumi tiek pārrakstīti tā, lai izlaistu rindas, kur tā ir false. Platajās (wide) daļās tiek rakstīta tikai šī viena kolonna; kompaktās daļas tiek pārrakstītas pilnībā.
Kas jāzina, pirms uz to paļauties:
- Dati kādu laiku paliek uz diska. Rindas fiziski izņem tikai vēlākas sapludināšanas, tāpēc vieta neatbrīvojas uzreiz. Ja vajag paredzamu tīrīšanu, dokumentācija iesaka tabulas iestatījumu
min_age_to_force_merge_secondsvai klasiskoALTER TABLE ... DELETE. - Pēc noklusējuma komanda gaida, līdz rindas ir atzīmētas.
lightweight_deletes_syncnoklusējums ir 2, kas pašreizējā pirmkodā nozīmē gaidīt visas replikas; 0 atgriežas uzreiz, un rindas var palikt redzamas, līdz fona mutācija beidzas. - Projekcijas to bloķē. Pēc noklusējuma
DELETEneizdodas tabulām ar projekcijām; MergeTree iestatījumslightweight_mutation_projection_mode(noklusējumsthrow) var to mainīt uzdropvairebuild. - Lasīšana maksā cenu. Dokumentācija brīdina, ka liela apjoma dzēšana šādā veidā var pasliktināt
SELECTveiktspēju, jo vaicājumi turpina filtrēt maskētās rindas, līdz sapludināšana tās izņem. - Particiju atlase.
ReplicatedMergeTreegadījumā nosacījumi uz particiju atslēguWHEREdaļā tiek automātiski izmantoti, lai skartu tikai atbilstošās particijas (optimize_mutations_with_partition_pruning, pēc noklusējuma ieslēgts). NereplicētamMergeTreeIN PARTITIONjāpievieno pašam.
ALTER TABLE DELETE: pārrakstīšana maskā
-- klasiskā mutācija: pārraksta katru skarto daļu
ALTER TABLE events DELETE WHERE event_date < '2024-01-01';
-- veciem datiem parasti daudz lētāk: dzēsiet veselas particijas
ALTER TABLE events DROP PARTITION '202312';
Mutāciju dokumentācija skaidri saka, kā tas darbojas: mutācijas MergeTree tabulās tiek izpildītas, pārrakstot veselas datu daļas. Daļa ar vienu atbilstošu rindu no piecdesmit miljoniem tiek uzrakstīta no jauna pilnībā. Dažas sekas:
- Nav atomitātes un atcelšanas. Daļas tiek aizstātas ar mutētām, tiklīdz katra ir gatava, tāpēc vaicājums mutācijas laikā redz sajaukumu. Kad mutācija iesniegta, to nevar atritināt.
- Tā pārdzīvo restartus. Iesniegta mutācija turpinās pēc servera restarta, tāpēc "restartēt un cerēt" to neatceļ.
- Ievietošana netiek bloķēta. Rindas, kas ievietotas pirms mutācijas iesniegšanas, tiek skartas; vēlāk ievietotās netiek.
- Stingra secība. Mutācijas katrai daļai tiek piemērotas izveides secībā. Lēna mutācija aiztur katru nākamo mutāciju tajā pašā tabulā, arī vēlākas vieglās dzēšanas.
- Pēc noklusējuma asinhroni.
mutations_syncnoklusējums ir 0:ALTERatgriežas uzreiz, un darbs notiek fonā. 1 gaida pašreizējā serverī, 2 visās replikās, 3 tikai aktīvajās replikās.
Mutāciju uzraudzība un apturēšana
Katrai mutācijai ir rinda tabulā system.mutations:
SELECT database, table, mutation_id, command, create_time,
parts_to_do, is_done, latest_failed_part, latest_fail_reason
FROM system.mutations
WHERE is_done = 0
ORDER BY create_time;
-- atceliet iestrēgušu mutāciju (jau pārrakstītās daļas paliek pārrakstītas)
KILL MUTATION WHERE database = 'default' AND table = 'events'
AND mutation_id = 'mutation_3.txt';
parts_to_do rāda, cik daļu vēl gaida. latest_fail_reason ir pirmā vieta, kur skatīties, ja mutācija nevirzās: bieži iemesli ir izteiksme, kas dažām rindām neizdodas, vai diska vietas vai atmiņas trūkums pārrakstīšanai. Ņemiet vērā, ka replicētām tabulām parts_to_do = 0 ne vienmēr nozīmē, ka mutācija ir pabeigta, jo ilga ievietošana vēl var radīt daļu, kas jāmutē.
KILL MUTATION atceļ iestrēgušu mutāciju, bet jau veiktās izmaiņas netiek atritinātas. Pārrakstītās daļas paliek pārrakstītas; pārējās saglabā vecās rindas. Pēc dzēšanas atcelšanas tabula ir daļēji izdzēstā stāvoklī, un jāizlemj, vai iesniegt laboto komandu atkārtoti.
Pabeigtās mutācijas sarakstā tiek glabātas līdz finished_mutations_to_keep (MergeTree iestatījumos pēc noklusējuma 100). Replicētām tabulām mutāciju rinda atrodas Keeper, tāpēc, ja Keeper nav pieejams, apstājas arī mutācijas; šo atkarību skaidrojām rakstā table is in readonly mode.
Lielas tabulas: kas mainās
- Diska vieta. Pārrakstīšana uzraksta katras skartās daļas jaunu versiju, pirms vecā tiek izņemta. Ja jūsu
WHEREnesakrīt ar particiju atslēgu, var tikt skartas visas daļas, un jūs faktiski pārrakstāt visu tabulu. Salīdziniet brīvo vietu ar skarto particiju izmēru, nevis ar dzēšamo rindu izmēru. - Fona pūls. Mutācijas konkurē ar sapludināšanu par tiem pašiem fona pavedieniem, CPU un disku. Liela pārrakstīšana palēnina sapludināšanu, un tabulā ar intensīvu ievietošanu tas var novest pie Too many parts.
- Mutāciju ierobežojumi. MergeTree iestatījumi mākslīgi palēnina mutācijas, kad tabulai ir 500 nepabeigtu mutāciju (
number_of_mutations_to_delay), un pie 1000 noraida jaunas ar "Too many mutations" (number_of_mutations_to_throw). GDPR uzdevums, kas sūta vienuDELETEuz katru lietotāju, to var sasniegt ātri. Apvienojiet ID vienā komandā arIN. - Replikas. Mutācijas tiek koordinētas caur Keeper, un ar
mutations_sync = 0jūsu klients nezina, kad pēdējā replika ir beigusi. Datiem, kuriem jābūt dzēstiem, gaidiet ar 2 vai pārbaudietsystem.mutationskatrā replikā. - Vieglais nav bezmaksas lielā mērogā. Atzīmējot lielu daļu lielas tabulas kā dzēstu, vaicājumiem paliek daudz maskētu rindu, ko izlaist, un vieta atgriežas tikai pēc sapludināšanas. Vecu datu dzēšanai particijas vai TTL gandrīz vienmēr ir labāki.
Plānojiet dzēšanu jau sākumā
Lētākā dzēšana ir tā, ko ieplānojāt, veidojot tabulu. Particionējiet pa mēnešiem vai dienām, ja vecos datus dzēš pēc vecuma, un tad dzēsiet particijas vai izmantojiet TTL klauzulu, lai dati beigtos automātiski. Ja regulāri jādzēš atsevišķi lietotāji vai ieraksti, apvienojiet šīs dzēšanas un rēķinieties ar maskētām rindām, līdz sapludināšana panāk. Atjauninājumiem, nevis dzēšanai, jaunākās ClickHouse versijās ir arī vieglais UPDATE ar ielāpu daļām (patch parts). Dokumentācija saka, ka tas paredzēts nelielām izmaiņām, līdz aptuveni 10% tabulas, un ka tas palielina slodzi vaicājumiem, kuriem jāpiemēro ielāpi.
Mūsu īkšķa likums: veci dati aiziet ar DROP PARTITION vai TTL, mērķtiecīgas dzēšanas ar apvienotu vieglo DELETE, un ALTER TABLE ... DELETE tikai tad, ja vieta vajadzīga tūlīt un disks ir pārbaudīts. Pirms jebkuras dzēšanas lielā tabulā apskatiet system.mutations: ja tur jau kaut kas ir iestrēdzis, jūsu dzēšana gaidīs aiz tā.
Kontrolsaraksts pirms rindu dzēšanas ClickHouse
- Vai dzēšanu var izteikt kā particiju dzēšanu vai TTL? Izmantojiet to.
- Pārbaudiet
system.mutations, vai tabulai nav nepabeigtu vai neveiksmīgu mutāciju. - Vieglajam
DELETEpārbaudiet projekcijas un nereplicētām tabulām pievienojietIN PARTITION. ALTER TABLE ... DELETEgadījumā novērtējiet skarto daļu izmēru un pārliecinieties par brīvo diska vietu.- Apvienojiet daudzas mazas dzēšanas vienā komandā.
- Izlemiet, kā gaidīt:
mutations_syncvailightweight_deletes_sync, vai uzraugietsystem.mutationskatrā replikā. - Sagatavojiet plānu
KILL MUTATIONgadījumam, atceroties, ka tas neatceļ jau pabeigtās daļas.
Galvenās atziņas
- ClickHouse daļas ir nemainīgas: dzēšana vai nu maskē rindas, vai pārraksta daļas.
- Vieglais
DELETEraksta_row_existsmasku; vieta atbrīvojas tikai pēc vēlākām sapludināšanām. ALTER TABLE ... DELETEpārraksta katru skarto daļu, nav atomārs un to nevar atritināt.- Mutācijas notiek secīgi, tāpēc viena iestrēgusi mutācija bloķē pārējās. Uzraugiet
system.mutations. - Lielās tabulās pārbaudiet disku, fona slodzi un 500/1000 mutāciju ierobežojumus.
- Veidojiet tabulas tā, lai veci dati aiziet caur particijām vai TTL.