Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

Vzhledem k tomu, že ClickHouse je specializovaný systém, je důležité při jeho používání brát v úvahu zvláštnosti jeho architektury. V této zprávě bude Alexey mluvit o příkladech typických chyb při používání ClickHouse, které mohou vést k neefektivní práci. Na praktických příkladech si ukážeme, jak může volba toho či onoho schématu zpracování dat řádově měnit výkon.

Ahoj všichni! Jmenuji se Alexey a vyrábím ClickHouse.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

Za prvé, spěchám vás hned potěšit, dnes vám neřeknu, co je ClickHouse. Abych byl upřímný, už mě to nebaví. Pokaždé ti říkám, co to je. A to už asi každý ví.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

Místo toho vám řeknu, jaký je možný rake, tedy jak lze ClickHouse zneužít. Ve skutečnosti byste se neměli bát, protože ClickHouse vyvíjíme jako systém, který je jednoduchý, pohodlný a funguje hned po vybalení. Vše nainstalováno, žádný problém.

Ale přesto je třeba mít na paměti, že tento systém je specializovaný a můžete snadno narazit na neobvyklý případ použití, který tento systém vyvede z komfortní zóny.

Takže, jaké jsou hrábě? V podstatě budu mluvit o samozřejmých věcech. Vše je každému jasné, každý všemu rozumí a může být rád, že je tak chytrý, a kdo nerozumí, naučí se něco nového.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

Prvním nejjednodušším příkladem, který se bohužel často vyskytuje, je velké množství vložek s malými šaržemi, tedy velké množství malých vložek.

Pokud vezmeme v úvahu, jak ClickHouse provádí vložení, pak můžete v jedné žádosti odeslat alespoň terabajt dat. To není problém.

A uvidíme, jaký bude typický výkon. Máme například tabulku s daty Yandex.Metrica. Hity. 105 některé sloupce. 700 bajtů nekomprimováno. A vložíme v pohodě dávky po milionu řádků.

Vložíme do tabulky MergeTree, získá se půl milionu řádků za sekundu. Skvělý. V replikované tabulce to bude o něco méně, asi 400 000 řádků za sekundu.

A pokud zapnete vložení kvora, získáte o něco menší, ale stále slušný výkon, 250 000krát za sekundu. Vkládání kvora je nezdokumentovaná funkce v ClickHouse*.

*od roku 2020, již zdokumentováno.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

Co se stane, když to uděláte špatně? Do tabulky MergeTree vložíme jeden řádek a dostaneme 59 řádků za sekundu. To je 10 000krát pomalé. V ReplicatedMergeTree - 6 řádků za sekundu. A pokud se kvorum zapne, získá se 2 řádky za sekundu. Podle mě je to nějaká naprostá kravina. Jak můžeš takhle zpomalit? Na mém tričku je dokonce napsáno, že ClickHouse by neměl zpomalovat. Ale přesto se to občas stane.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

Ve skutečnosti je to náš nedostatek. Mohli jsme to dobře zařídit, ale neudělali jsme to. A my ne, protože náš scénář to nepotřeboval. Už jsme měli várky. Právě jsme dostali dávky u vchodu a žádné problémy. Zapojte a vše funguje dobře. Ale samozřejmě jsou možné všechny možné scénáře. Například když máte spoustu serverů, na kterých se generují data. A nevkládají data tak často, ale stále dostávají časté vkládání. A tomu se musíte nějak vyhnout.

Z technického hlediska je podstatné, že když uděláte insert v ClickHouse, data se nedostanou do žádné paměti. Nemáme ani skutečnou strukturu logů MergeTree, ale pouze MergeTree, protože neexistuje ani log ani memTable. Jen okamžitě zapíšeme data do souborového systému, již rozložená do sloupců. A pokud máte 100 sloupců, bude potřeba zapsat více než 200 souborů do samostatného adresáře. To vše je velmi těžkopádné.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

A vyvstává otázka: "Jak to udělat správně?" V takové situaci je stále třeba nějak zapisovat data do ClickHouse.

Metoda 1. Toto je nejjednodušší způsob. Použijte nějaký druh distribuované fronty. Například Kafka. Stačí vyjmout data z Kafky, my je dávkujeme jednou za sekundu. A vše bude v pořádku, nahráváte, vše funguje dobře.

Nevýhody jsou, že Kafka je další těžkopádný distribuovaný systém. Chápu i to, jestli už Kafku ve firmě máte. Je to dobré, pohodlné. Ale pokud tam není, měli byste si to třikrát rozmyslet, než do svého projektu přetáhnete další distribuovaný systém. A tak stojí za zvážení alternativ.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

Metoda 2. Tady je taková oldschoolová alternativa a přitom velmi jednoduchá. Máte nějaký server, který generuje vaše logy. A pouze zapisuje vaše protokoly do souboru. A jednou za vteřinu například tento soubor přejmenujeme, otevřeme nový. A samostatný skript buď cronem nebo nějakým démonem vezme nejstarší soubor a zapíše ho do ClickHouse. Pokud budete zapisovat protokoly jednou za sekundu, pak bude vše v pořádku.

Nevýhodou této metody ale je, že pokud váš server, na kterém se generují logy, někam zmizel, zmizí i data.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

Metoda 3. Existuje další zajímavý způsob, který je bez dočasných souborů. Například máte nějaký reklamní spinner nebo jiného zajímavého démona, který generuje data. A můžete akumulovat spoustu dat přímo v paměti RAM, ve vyrovnávací paměti. A když uplyne dostatečné množství času, odložíte tento buffer, vytvoříte nový a to, co se již nashromáždilo do ClickHouse, vložíte do samostatného vlákna.

Na druhou stranu data také zmizí s kill -9. Pokud váš server vypadne, ztratíte tato data. A dalším problémem je, že pokud nemůžete zapisovat do databáze, vaše data se budou hromadit v RAM. A buď dojde RAM, nebo prostě přijdete o data.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

Metoda 4. Další zajímavý způsob. Máte nějaký serverový proces. A může odesílat data do ClickHouse najednou, ale udělat to v jednom připojení. Například jsem poslal http požadavek s přenosovým kódováním: chunked with insert. A generuje bloky ne příliš zřídka, můžete poslat každý řádek, i když bude existovat režie pro rámování těchto dat.

V tomto případě však budou data odeslána do ClickHouse okamžitě. A samotný ClickHouse je bude vyrovnávat.

Jsou tu ale i problémy. Nyní ztratíte data, včetně toho, když je váš proces zabit a pokud je zabit proces ClickHouse, protože to bude neúplná vložka. A v ClickHouse jsou vložky atomické až do určité stanovené prahové hodnoty ve velikosti řádků. V zásadě jde o zajímavý způsob. Lze také použít.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

Metoda 5. Zde je další zajímavý způsob. Jedná se o jakýsi komunitou vyvinutý server pro dávkování dat. Sám jsem se na to nedíval, takže nemohu nic zaručit. Na samotný ClickHouse však neexistují žádné záruky. To je také open source, ale na druhou stranu se dalo zvyknout na nějaký standard kvality, který se snažíme poskytovat. Ale k této věci - nevím, jděte na GitHub, podívejte se na kód. Možná napsali něco dobrého.

*od roku 2020 je třeba také zvážit Kotěcí dům.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

Metoda 6. Dalším způsobem je použití vyrovnávacích tabulek. Výhodou této metody je, že je velmi snadné ji začít používat. Vytvořte tabulku Buffer a vložte do ní.

Nevýhodou ale je, že problém není zcela vyřešen. Pokud rychlostí typu MergeTree musíte seskupovat data podle jedné dávky za sekundu, pak rychlostí v tabulce vyrovnávací paměti musíte seskupit alespoň několik tisíc za sekundu. Pokud jich bude více než 10 000 za sekundu, bude to stále špatné. A pokud vkládáte v dávkách, pak jste viděli, že se tam získá sto tisíc řádků za sekundu. A to už je na poměrně těžkých datech.

A také tabulky bufferů nemají log. A pokud je s vaším serverem něco v nepořádku, data budou ztracena.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

A jako bonus jsme nedávno měli možnost sbírat data od Kafky v ClickHouse. Je zde stolní motor - Kafka. Jednoduše tvoříte. A můžete na něj pověsit zhmotněné pohledy. V tomto případě vytáhne data z Kafky a vloží je do tabulek, které potřebujete.

A co je na této příležitosti obzvláště potěšující, je to, že jsme ji nevyužili. Toto je komunitní funkce. A když říkám „komunitní funkce“, říkám to bez jakéhokoli pohrdání. Přečetli jsme kód, provedli kontrolu, mělo by to fungovat dobře.

* od roku 2020 existuje podobná podpora RabbitMQ.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

Co ještě může být nepohodlné nebo neočekávané při vkládání dat? Pokud uděláte dotaz na vložení hodnot a zapíšete některé vypočítané výrazy do hodnot. Například now() je také vyhodnocený výraz. A v tomto případě je ClickHouse nucen spustit interpret těchto výrazů pro každý řádek a výkon klesne o řády. Je lepší se tomu vyhnout.

* v tuto chvíli je problém zcela vyřešen, při použití výrazů v VALUES již nedochází k regresi výkonu.

Dalším příkladem, kde mohou nastat nějaké problémy, je situace, kdy vaše data v jedné dávce patří do několika oddílů. Ve výchozím nastavení ClickHouse rozděluje podle měsíce. A pokud vložíte dávku milionů řádků a jsou tam data na několik let, budete tam mít několik desítek oddílů. A to se rovná tomu, že budou dávky několik desítekkrát menší, protože uvnitř jsou vždy nejprve rozděleny na oddíly.

* nedávno v ClickHouse v experimentálním režimu přidána podpora pro kompaktní formát bloků a bloků v paměti RAM s protokolem pro zápis dopředu, což problém téměř úplně řeší.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

Nyní zvažte druhý typ problému - typování dat.

Zadávání dat může být striktní a někdy i řetězcové. String - to je, když jste právě vzali a prohlásili, že máte všechna pole typu string. Je to na hovno. Nemusíte to dělat.

Pojďme přijít na to, jak to udělat správně v případech, kdy chcete říct, že máme nějaké pole, řetězec a nechat ClickHouse, aby si na to přišel sám, ale já si nedám parní lázeň. Ale přesto stojí za to vynaložit určité úsilí.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

Máme například IP adresu. V jednom případě jsme jej uložili jako řetězec. Například 192.168.1.1. Jinak to bude číslo typu UInt32*. Na IPv32 adresu stačí 4 bitů.

Za prvé, kupodivu budou data komprimována přibližně stejně. Rozdíl tam bude, jistě, ale ne tak velký. S diskovými I/O tedy nejsou žádné zvláštní problémy.

Existuje však vážný rozdíl v době CPU a době provádění dotazu.

Počítejme počet jedinečných IP adres, pokud jsou uloženy jako čísla. Ukazuje se, že 137 milionů řádků za sekundu. Pokud je to stejné jako řádky, pak 37 milionů řádků za sekundu. Nevím, proč se tato náhoda stala. Sám jsem tyto požadavky splnil. Ale přesto asi 4x pomaleji.

A pokud spočítáte rozdíl v místě na disku, tak tam je také rozdíl. A rozdíl je asi čtvrtinový, protože unikátních IP adres je poměrně hodně. A pokud by tam byly řádky s malým počtem různých hodnot, pak by byly ve slovníku klidně stlačeny do přibližně stejného objemu.

A čtyřnásobný časový posun neleží na silnici. Možná vás to samozřejmě nezajímá, ale když vidím takový rozdíl, je mi smutno.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

Podívejme se na různé případy.

1. Jeden případ, kdy máte několik různých jedinečných hodnot. V tomto případě používáme jednoduchou praxi, kterou pravděpodobně znáte a můžete ji použít pro jakýkoli DBMS. To vše dává smysl nejen pro ClickHouse. Stačí zapsat číselné identifikátory do databáze. A můžete převést na řetězce a zpět na straně vaší aplikace.

Máte například region. A vy se to snažíte uložit jako řetězec. A bude tam napsáno: Moskva a Moskevská oblast. A když vidím, že je tam napsáno „Moskva“, tak to ještě nic není, a když je MO, je to nějak úplně smutné. Tolik bajtů.

Místo toho si jednoduše zapíšeme číslo Ulnt32 a 250. V Yandexu máme 250, ale vaše se může lišit. Pro jistotu řeknu, že ClickHouse má vestavěnou schopnost pracovat s geobází. Jednoduše si zapíšete adresář s regiony, včetně hierarchického, tj. bude tam Moskva, Moskevská oblast a vše, co potřebujete. A můžete převádět na úrovni požadavku.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

Druhá možnost je přibližně stejná, ale s podporou uvnitř ClickHouse. Je to datový typ Enum. Jednoduše zapíšete všechny hodnoty, které potřebujete, do Enum. Například typ zařízení a napište tam: desktop, mobil, tablet, TV. Pouze 4 možnosti.

Nevýhodou je, že je potřeba pravidelně měnit. Byla přidána pouze jedna možnost. Vyrábíme alter stůl. Ve skutečnosti je alter table v ClickHouse zdarma. Zvláště zdarma pro Enum, protože data na disku se nemění. Ale přesto alter získá zámek * na stole a musí počkat, dokud nebudou dokončeny všechny výběry. A teprve poté, co bude tato změna provedena, to znamená, že stále existují nějaké nepříjemnosti.

* v posledních verzích ClickHouse je ALTER zcela neblokující.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

Další možností zcela unikátní pro ClickHouse je připojení externích slovníků. V ClickHouse můžete psát čísla a uchovávat své adresáře v jakémkoli systému, který vám vyhovuje. Můžete například použít: MySQL, Mongo, Postgres. Můžete si dokonce vytvořit vlastní mikroslužbu, která bude tato data odesílat přes http. A na úrovni ClickHouse napíšete funkci, která tato data převede z čísel na řetězce.

Toto je specializovaný, ale velmi účinný způsob, jak provést spojení na externí tabulce. A jsou dvě možnosti. V jedné možnosti budou tato data plně ukládána do mezipaměti, plně přítomna v paměti RAM a v určitých intervalech aktualizována. A v další možnosti, pokud se tato data nevejdou do RAM, můžete je částečně ukládat do mezipaměti.

Zde je příklad. Existuje Yandex.Direct. A je tu reklamní společnost a bannery. Inzertních společností jsou pravděpodobně desítky milionů. A zhruba se vejde do RAM. A transparentů jsou miliardy, nevejdou se. A my používáme slovník uložený v mezipaměti z MySQL.

Jediným problémem je, že slovník uložený v mezipaměti bude fungovat dobře, pokud se míra návštěvnosti blíží 100 %. Pokud bude menší, tak při zpracování požadavků na každý datový balíček bude nutné skutečně vzít chybějící klíče a jít vzít data z MySQL. O ClickHouse to stále mohu zaručit - ano, nezpomaluje se, nebudu mluvit o jiných systémech.

A jako bonus jsou slovníky velmi snadným způsobem, jak zpětně aktualizovat data v ClickHouse. To znamená, že jste měli přehled o reklamních společnostech, uživatel prostě změnil reklamní společnost a ve všech starých datech, ve všech přehledech, se tato data také změnila. Pokud zapíšete řádky přímo do tabulky, nebudete je moci aktualizovat.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

Další způsob, když nevíte, kde získat identifikátory pro vaše řetězce. můžete jen hashovat. A nejjednodušší možností je vzít 64bitový hash.

Jediným problémem je, že pokud je hash 64bitový, téměř jistě budete mít kolize. Protože pokud existuje miliarda čar, pak se pravděpodobnost již stává hmatatelnou.

A takhle hašovat jména reklamních společností by nebylo moc dobré. Pokud se reklamní kampaně různých společností promíchají, bude v tom něco nepochopitelného.

A existuje jednoduchý trik. Pravda, pro vážná data se to také moc nehodí, ale pokud něco moc vážného není, tak do klíče slovníku jednoduše přidejte další identifikátor klienta. A pak budete mít kolize, ale pouze v rámci jednoho klienta. A tuto metodu používáme pro mapu odkazů v Yandex.Metrica. Máme tam adresy URL, ukládáme hashe. A samozřejmě víme, že existují konflikty. Ale když se zobrazí stránka, tak pravděpodobnost, že se na jedné stránce jednoho uživatele drží nějaké adresy URL pohromadě a toho si všimneme, pak to lze zanedbat.

Jako bonus pro mnoho operací stačí pouze hashe a samotné řetězce nelze nikam ukládat.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

Další příklad, pokud jsou řetězce krátké, jako jsou domény webových stránek. Mohou být uloženy tak, jak jsou. Nebo například jazyk prohlížeče ru je 2 bajty. Samozřejmě je mi těch bajtů líto, ale nebojte, 2 bajty nejsou škoda. Prosím, nech to tak, jak je, neboj.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

Jiný případ je, když je naopak strun hodně a zároveň je v nich spousta unikátů a i sada je potenciálně neomezená. Typickým příkladem jsou vyhledávací fráze nebo adresy URL. Hledané fráze, včetně překlepů. Podívejme se, kolik jedinečných vyhledávacích frází za den. A ukazuje se, že jsou téměř polovinou všech událostí. A v tomto případě si možná myslíte, že potřebujete normalizovat data, spočítat identifikátory a dát je do samostatné tabulky. Ale to nemusíte dělat. Jen ponechte tyto řádky tak, jak jsou.

Lepší - nic nevymýšlejte, protože pokud to uložíte samostatně, budete muset provést spojení. A toto spojení je v nejlepším případě náhodný přístup k paměti, pokud se stále vejde do paměti. Pokud se nehodí, budou obecně problémy.

A pokud jsou data uložena na místě, pak se jednoduše načtou ve správném pořadí ze souborového systému a vše je v pořádku.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

Pokud máte adresy URL nebo nějaký jiný složitý dlouhý řetězec, pak byste měli myslet na to, že si můžete předem spočítat nějaký squeeze a napsat to do samostatného sloupce.

Pro adresy URL můžete například uložit doménu samostatně. A pokud opravdu potřebujete doménu, pak stačí použít tento sloupec a adresy URL budou lhát a ani se jich nedotknete.

Podívejme se, jaký je v tom rozdíl. ClickHouse má specializovanou funkci, která vypočítá doménu. Je velmi rychlý, optimalizovali jsme ho. A upřímně řečeno, nesplňuje ani RFC, ale přesto bere v úvahu vše, co potřebujeme.

A v jednom případě jednoduše získáme adresy URL a vypočítáme doménu. Ukazuje se to 166 milisekund. A pokud vezmete hotovou doménu, pak se ukáže pouze 67 milisekund, tedy téměř třikrát rychleji. A rychleji, ne proto, že bychom potřebovali provádět nějaké výpočty, ale proto, že čteme méně dat.

Z nějakého důvodu jeden požadavek, který je pomalejší, získá vyšší rychlost v gigabajtech za sekundu. Protože čte více gigabajtů. Jedná se o zcela nadbytečná data. Zdá se, že požadavek běží rychleji, ale jeho dokončení trvá déle.

A když se podíváte na množství dat na disku, ukáže se, že adresa URL je 126 megabajtů a doména pouze 5 megabajtů. Ukazuje se to 25krát méně. Dotaz je však stále jen 4krát rychlejší. Ale to proto, že data jsou horká. A kdyby byla zima, pravděpodobně by to bylo 25krát rychlejší kvůli I/O disku.

Mimochodem, když vyhodnotíš, o kolik je doména menší než url, tak to vyjde asi 4x. Ale z nějakého důvodu data na disku zabírají 25x méně. Proč? Kvůli kompresi. A adresa URL je komprimována a doména je komprimována. Adresa URL však často obsahuje spoustu odpadků.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

A samozřejmě stojí za to používat správné datové typy, které jsou speciálně navrženy pro správné hodnoty nebo které se hodí. Pokud používáte IPv4, uložte UInt32*. Pokud IPv6, pak FixedString(16), protože adresa IPv6 je 128 bitů, tj. ukládat přímo v binárním formátu.

Ale co když někdy máte adresy IPv4 a někdy IPv6? Ano, můžete si ponechat obojí. Jeden sloupec pro IPv4, druhý pro IPv6. Samozřejmostí je možnost mapování IPv4 na IPv6. To bude také fungovat, ale pokud často ve svých požadavcích potřebujete adresu IPv4, bylo by hezké ji umístit do samostatného sloupce.

* ClickHouse má nyní samostatné datové typy IPv4, IPv6, které ukládají data stejně efektivně jako čísla, ale reprezentují je stejně pohodlně jako řetězce.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

Je také důležité poznamenat, že se vyplatí zpracovat data předem. Přijdou k vám například nějaké surové kulatiny. A možná byste je neměli hned dávat do ClickHouse, ačkoli je velmi lákavé nedělat nic a všechno bude fungovat. Ale stále stojí za to provést ty výpočty, které jsou možné.

Například verze prohlížeče. V nějakém sousedním oddělení, na které nechci ukazovat prstem, je tam verze prohlížeče uložena takto, tedy jako řetězec: 12.3. A pak, aby vytvořili sestavu, vezmou tento řetězec a vydělí jej polem a poté prvním prvkem pole. Vše se přirozeně zpomaluje. Zeptal jsem se, proč to dělají. Řekli mi, že nemají rádi předčasnou optimalizaci. A nemám rád předčasný pesimismus.

V tomto případě by tedy bylo správnější rozdělit do 4 sloupců. Zde se nebojte, protože toto je ClickHouse. ClickHouse je sloupcová databáze. A čím více úhledných malých sloupků, tím lépe. Bude 5 BrowserVersion, vytvořte 5 sloupců. Tohle je fajn.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

Nyní zvažte, co dělat, pokud máte hodně velmi dlouhých řetězců, velmi dlouhých polí. V ClickHouse se vůbec nemusí ukládat. Místo toho můžete v ClickHouse uložit pouze nějaký identifikátor. A tyhle dlouhé fronty je šoupnou do nějakého jiného systému.

Například jedna z našich analytických služeb má nějaké parametry události. A pokud k událostem přijde hodně parametrů, jednoduše uložíme prvních 512, které se objeví. Protože 512 není škoda.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

A pokud se nemůžete rozhodnout pro své datové typy, můžete také zapisovat data do ClickHouse, ale do dočasné tabulky typu Log, která je speciální pro dočasná data. Poté můžete analyzovat, jaký druh distribuce hodnot tam máte, co tam obecně je a vytvořit správné typy.

* Nyní má ClickHouse datový typ Nízká kardinalita což umožňuje efektivně ukládat struny s menší námahou.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

Nyní zvažte další zajímavý případ. Někdy věci fungují na lidi zvláštním způsobem. Jdu a uvidím tohle. A hned se zdá, že to udělal nějaký velmi zkušený, chytrý admin, který má bohaté zkušenosti s nastavením MySQL verze 3.23.

Zde vidíme tisíc tabulek, z nichž každá obsahuje zbytek dělení není jasné čím tisíci.

V zásadě respektuji zkušenosti jiných lidí, včetně pochopení, jaké utrpení lze touto zkušeností získat.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

A důvody jsou víceméně jasné. Jsou to staré stereotypy, které se mohly nashromáždit při práci s jinými systémy. Například tabulky MyISAM nemají seskupený primární klíč. A tento způsob sdílení dat může být zoufalým pokusem získat stejnou funkcionalitu.

Dalším důvodem je, že na velkých stolech je obtížné provádět jakékoli změny. Vše bude zablokováno. I když v moderních verzích MySQL už tento problém není tak závažný.

Nebo třeba microsharding, ale o tom později.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

V ClickHouse to nemusíte dělat, protože za prvé, primární klíč je seskupený, data jsou uspořádána podle primárního klíče.

A někdy se mě lidé ptají: „Jak se mění výkon dotazů na rozsah v ClickHouse s velikostí tabulky?“. Říkám, že se to vůbec nemění. Například máte tabulku s miliardou řádků a čtete rozsah jednoho milionu řádků. Vše je v pořádku. Pokud má tabulka bilion řádků a čtete milion řádků, bude to téměř stejné.

A za druhé, nejsou vyžadovány žádné části, jako jsou ruční oddíly. Když půjdete dovnitř a podíváte se, co je v systému souborů, uvidíte, že tabulka je docela vážná věc. A uvnitř je něco jako přepážky. To znamená, že ClickHouse udělá vše za vás a vy nemusíte trpět.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

Alter in ClickHouse je zdarma, pokud změníte sloupec add/drop.

A neměli byste dělat malé tabulky, protože pokud máte v tabulce 10 řádků nebo 10 000 řádků, tak to vůbec nevadí. ClickHouse je systém, který optimalizuje propustnost, nikoli latenci, takže nemá smysl zpracovávat 10 linek.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

Je správné použít jeden velký stůl. Zbavte se starých stereotypů, vše bude v pořádku.

A jako bonus máme v nejnovější verzi možnost vytvořit libovolný rozdělovací klíč, aby bylo možné provádět nejrůznější operace údržby na jednotlivých oddílech.

Například potřebujete mnoho malých tabulek, například když je potřeba zpracovat nějaká mezilehlá data, dostáváte bloky a potřebujete na nich provést transformaci před zápisem do finální tabulky. Pro tento případ je tu nádherný stolní engine - StripeLog. Je to jako TinyLog, jen lepší.

* Nyní má ClickHouse více vstup tabulkové funkce.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

Dalším anti-vzorem je mikrosharding. Například potřebujete shardovat data a máte 5 serverů a zítra tam bude 6 serverů. A přemýšlíte, jak tato data znovu vyvážit. A místo toho se nerozdělujete na 5 střípků, ale na 1 000 úlomků. A pak namapujete každý z těchto mikroshardů na samostatný server. A uspějete na jednom serveru, například 200 ClickHouse. Samostatná instance na samostatných portech nebo samostatných databázích.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

Ale v ClickHouse to není moc dobré. Protože i jedna instance ClickHouse se snaží využít všechny dostupné zdroje serveru ke zpracování jednoho požadavku. To znamená, že máte nějaký server a tam například 56 procesorových jader. Spouštíte dotaz, který trvá jednu sekundu a bude používat 56 jader. A pokud tam umístíte 200 ClickHouses na jeden server, pak se ukáže, že se spustí 10 000 vláken. Obecně bude všechno velmi špatné.

Dalším důvodem je, že rozdělení práce v těchto instancích bude nerovnoměrné. Někdo skončí dříve, někdo později. Pokud by se to všechno stalo v jednom případě, pak by sám ClickHouse přišel na to, jak správně distribuovat data mezi streamy.

A dalším důvodem je, že budete mít meziprocesorovou komunikaci přes TCP. Data budou muset být serializována, deserializována, a to je obrovské množství mikroshardů. Prostě to nepůjde.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

Další antivzor, ​​i když jej lze jen stěží nazvat antivzorem. Jedná se o velké množství předagregace.

Obecně je předagregace dobrá. Měli jste miliardu řádků, agregovali jste je a bylo z toho 1 000 řádků a nyní se dotaz provede okamžitě. Všechno je skvělé. Takhle to můžete udělat. A za tímto účelem má i ClickHouse speciální typ tabulky AggregatingMergeTree, který provádí inkrementální agregaci při vkládání dat.

Ale jsou chvíle, kdy si myslíte, že budeme takto agregovat data a takto agregovat data. A v nějakém sousedním oddělení, ani nechci říkat v jakém, používají tabulky SummingMergeTree pro sčítání podle primárního klíče a jako primární klíč se používá 20 sloupců. Pro jistotu jsem změnil názvy některých sloupců kvůli konspiraci, ale to je tak vše.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

A takové problémy vznikají. Za prvé, množství dat, které máte, se příliš nesníží. Například se sníží třikrát. Třikrát by byla dobrá cena, kdybychom si mohli dovolit neomezenou analýzu, která přichází s neagregovanými daty. Pokud jsou data agregovaná, pak místo analýzy získáte pouze mizerné statistiky.

A co je obzvlášť dobré? Že tito lidé z vedlejšího oddělení občas zajdou a požádají o přidání dalšího sloupce do primárního klíče. To znamená, že jsme takto agregovali data a teď chceme trochu víc. V ClickHouse však neexistuje žádný alter primární klíč. Proto musíte psát některé skripty v C++. A nemám rád skripty, i když jsou v C++.

A když se podíváte na to, k čemu byl ClickHouse vytvořen, pak jsou neagregovaná data přesně tím scénářem, pro který se zrodil. Pokud používáte ClickHouse pro neagregovaná data, pak děláte vše správně. Pokud agregujete, pak je to někdy odpustitelné.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

Dalším zajímavým případem jsou požadavky v nekonečné smyčce. Občas zajdu na nějaký produkční server a podívám se tam na proces show. A pokaždé, když zjistím, že se děje něco hrozného.

Zde je například toto. Okamžitě je jasné, že vše bylo možné vyřídit na jeden požadavek. Stačí napsat url a tam seznam.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

Proč je mnoho takových požadavků v nekonečné smyčce špatných? Pokud se index nepoužívá, budete mít mnoho průchodů přes stejná data. Ale pokud se použije index, tak máš primární klíč na ru a napíšeš tam url = něco. A myslíte si, že jedna url bude bodově přečtena z tabulky, vše bude v pořádku. Ale opravdu ne. Protože ClickHouse dělá vše v dávkách.

Když potřebuje přečíst nějaký rozsah dat, přečte o něco více, protože index v ClickHouse je řídký. Tento index neumožňuje najít jeden jednotlivý řádek v tabulce, pouze nějaký rozsah. A data jsou komprimována v blocích. Abyste mohli přečíst jeden řádek, musíte vzít celý blok a rozbalit jej. A pokud spustíte spoustu dotazů, budete mít spoustu průsečíků a budete mít spoustu práce znovu a znovu.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

A jako bonus můžete vidět, že v ClickHouse byste se neměli bát přenést do sekce IN i megabajty a dokonce stovky megabajtů. Z naší praxe si pamatuji, že když předáme hromadu hodnot v sekci IN v MySQL, například tam předáme 100 megabajtů nějakých čísel, pak MySQL zabere 10 gigabajtů paměti a nic jiného se nestane to, všechno funguje špatně.

A druhá věc je, že v ClickHouse, pokud vaše dotazy používají index, pak to není vždy pomalejší než úplné skenování, tj. pokud potřebujete přečíst téměř celou tabulku, půjde to sekvenčně a přečte celou tabulku. Obecně na to přijde.

Existují však určité potíže. Například, že IN s poddotazem nepoužívá index. Ale to je náš problém a musíme ho napravit. Není zde nic zásadního. Pojďme na to*.

A další zajímavostí je, že pokud máte velmi dlouhý požadavek a probíhá distribuované zpracování požadavku, pak bude tento velmi dlouhý požadavek odeslán na každý server bez komprese. Například 100 megabajtů a 500 serverů. V souladu s tím bude po síti přeneseno 50 gigabajtů. Bude přenesen a poté bude vše úspěšně provedeno.

* již používá; vše bylo opraveno, jak bylo slíbeno.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

A je docela běžné, pokud požadavky přicházejí z API. Například jste provedli nějakou službu. A pokud někdo potřebuje vaši službu, otevřete API a doslova o dva dny později vidíte, že se děje něco nepochopitelného. Všechno je přetížené a přicházejí nějaké hrozné požadavky, které nikdy neměly být.

A řešení je jen jedno. Pokud jste otevřeli API, budete jej muset vyjmout. Například zadat nějaké kvóty. Jiné rozumné možnosti nejsou. Jinak rovnou napíšou scénář a budou problémy.

A ClickHouse má speciální funkci – tou je výpočet kvót. Kromě toho můžete přenést svůj kvótový klíč. Jedná se například o interní ID uživatele. A kvóty budou vypočítány nezávisle pro každou z nich.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

Nyní další zajímavost. Toto je ruční replikace.

Znám mnoho případů, kdy, přestože má ClickHouse vestavěnou podporu replikace, lidé replikují ClickHouse ručně.

Jaký je princip? Máte kanál pro zpracování dat. A funguje samostatně například v různých datových centrech. Stejná data zapisujete stejným způsobem do ClickHouse. Pravda, praxe ukazuje, že data se budou stále rozcházet kvůli některým zvláštnostem ve vašem kódu. Doufám, že v tom vašem.

A pravidelně je stále nutné ručně synchronizovat. Například jednou za měsíc administrátoři provedou rsync.

Ve skutečnosti je mnohem jednodušší použít vestavěnou replikaci v ClickHouse. Mohou však existovat určité kontraindikace, protože k tomu musíte použít ZooKeeper. Na ZooKeeper neřeknu nic špatného, ​​v zásadě systém funguje, ale stává se, že ho lidé nepoužívají kvůli java-fobii, protože ClickHouse je tak dobrý systém napsaný v C ++, který můžete používat a vše bude v pořádku. A ZooKeeper v Javě. A nějak se ani nechcete dívat, ale pak můžete použít ruční replikaci.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

ClickHouse je praktický systém. Zohledňuje vaše potřeby. Pokud máte ruční replikaci, můžete vytvořit distribuovanou tabulku, která se podívá na vaše ruční repliky a provede mezi nimi převzetí služeb při selhání. A dokonce existuje speciální možnost, která vám umožní vyhnout se propadům, i když jsou vaše linie systematicky divergentní.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

Dále mohou nastat problémy, pokud používáte primitivní tabulkové motory. ClickHouse je takový konstruktor, který má spoustu různých tabulkových enginů. Pro všechny závažné případy, jak je napsáno v dokumentaci, použijte tabulky z rodiny MergeTree. A vše ostatní - to je tak, pro jednotlivé případy nebo pro testy.

V tabulce MergeTree nemusíte mít žádné datum a čas. Stále můžete používat. Pokud zde není datum a čas, napište, že výchozí hodnota je 2000. Bude to fungovat a nebude to vyžadovat zdroje.

A v nové verzi serveru můžete dokonce určit, že máte vlastní rozdělení bez klíče oddílu. Bude to stejné.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

Na druhou stranu lze použít primitivní stolní motory. Například jednou vyplňte data a uvidíte, zkrouťte a smažte. Můžete použít Log.

Nebo ukládání malých objemů pro mezizpracování je StripeLog nebo TinyLog.

Paměť lze použít, pokud je malé množství dat a stačí něco zkroutit v RAM.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

ClickHouse nemá moc rád renormalizovaná data.

Zde je typický příklad. Jedná se o obrovské množství adres URL. Položíte je na sousední stůl. A pak jsme se rozhodli udělat s nimi JOIN, ale to zpravidla nebude fungovat, protože ClickHouse podporuje pouze Hash JOIN. Pokud není dostatek paměti RAM pro velké množství dat, se kterými se lze připojit, pak JOIN nebude fungovat *.

Pokud mají data vysokou mohutnost, pak se nebojte, uložte je v denormalizované podobě, adresy URL jsou přímo umístěny v hlavní tabulce.

* a nyní má ClickHouse také slučovací spojení a funguje v podmínkách, kdy se mezilehlá data nevejdou do paměti RAM. To je ale neúčinné a doporučení zůstává platné.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

Pár dalších příkladů, ale už pochybuji, zda jsou anti-vzory nebo ne.

ClickHouse má jednu známou nevýhodu. Neví, jak aktualizovat *. V jistém smyslu je to dokonce dobře. Pokud máte nějaká důležitá data, například účetnictví, nikdo vám je nebude moci odeslat, protože nejsou žádné aktualizace.

* Podpora pro aktualizaci a mazání v dávkovém režimu byla přidána již dlouho.

Existuje však několik speciálních způsobů, které umožňují zobrazování aktualizací na pozadí. Například tabulky typu ReplaceMergeTree. Provádějí aktualizace během sloučení na pozadí. Můžete to vynutit pomocí tabulky optimalizace. Ale nedělejte to příliš často, protože by to zcela přepsalo oddíl.

Distribuované JOINy ​​v ClickHouse – to také špatně řeší plánovač dotazů.

Špatné, ale někdy OK.

Použití ClickHouse pouze ke zpětnému čtení dat pomocí select*.

Nedoporučoval bych používat ClickHouse pro objemné výpočty. Není to ale tak úplně pravda, protože od tohoto doporučení se již vzdalujeme. A nedávno jsme přidali možnost aplikovat modely strojového učení v ClickHouse - Catboost. A znepokojuje mě to, protože si říkám: „To je hrůza. To je, kolik cyklů na bajt to dopadá! Je mi škoda spouštět hodinové cykly po bytech.

Efektivní využití ClickHouse. Alexey Milovidov (Yandex)

Ale nebojte se, nainstalujte ClickHouse, vše bude v pořádku. Pokud něco, máme komunitu. Mimochodem, komunita jste vy. A pokud budete mít nějaké problémy, můžete jít alespoň na náš chat a doufám, že vám pomůže.

otázky

Díky za zprávu! Kde si stěžovat na havárii ClickHouse?

Můžete mi osobně stěžovat hned teď.

Nedávno jsem začal používat ClickHouse. Okamžitě jsem zrušil rozhraní cli.

Máte štěstí.

O něco později jsem server upustil s malým výběrem.

Máš talent.

Otevřel jsem chybu GitHubu, ale byla ignorována.

Uvidíme.

Aleksey mě nalákal, abych se zúčastnil hlášení, a slíbil mi, že mi řekne, jak uvnitř mačkáte data.

Velmi jednoduchý.

Tohle jsem si uvědomil včera. Další podrobnosti.

Neexistují žádné hrozné triky. Je to jen komprese blok po bloku. Výchozí nastavení je LZ4, můžete povolit ZSTD*. Bloky od 64 kB do 1 MB.

* K dispozici je také podpora pro specializované kompresní kodeky, které lze použít v řetězci s jinými algoritmy.

Jsou bloky jen nezpracovaná data?

Ne úplně syrové. Existují pole. Pokud máte číselný sloupec, pak jsou čísla v řádku naskládána do pole.

To je jasné.

Alexey, příklad, který byl s uniqExact over IPs, tj. skutečnost, že uniqExact trvá déle, než se počítá podle řetězců než podle čísel, a tak dále. Co když použijeme fintu ušima a odlijeme v okamžiku korektury? To znamená, že jste jakoby řekli, že se to na disku moc neliší. Pokud budeme číst řádky z disku, odlévat, pak budeme mít agregáty rychlejší nebo ne? Nebo zde stále okrajově získáváme? Zdá se mi, že jste to testovali, ale z nějakého důvodu jste to neuvedli v benchmarku.

Myslím, že to bude pomalejší než žádné obsazení. V tomto případě musí být IP adresa analyzována z řetězce. V ClickHouse je samozřejmě optimalizován i parsování IP adres. Velmi jsme se snažili, ale na stejném místě máte čísla napsaná v desetitisícovém tvaru. Velmi nepříjemné. Na druhou stranu funkce uniqExact bude pracovat na řetězcích pomaleji, nejen proto, že se jedná o řetězce, ale také proto, že je zvolena jiná specializace algoritmu. Řetězce jsou prostě jinak řešeny.

A když vezmeme primitivnější datový typ? Například si zapsali ID uživatele, které máme, zapsali to jako řádek a pak to odevzdali, bude to zábavnější nebo ne?

Pochybuji. Myslím, že to bude ještě smutnější, protože přeci jen, parsování čísel je vážný problém. Zdá se mi, že tento kolega měl dokonce zprávu o tom, jak obtížné je analyzovat čísla v desetitisícovém tvaru, ale možná ne.

Alexey, moc děkuji za zprávu! A moc děkujeme za ClickHouse! Mám dotaz ohledně plánů. Existuje v plánech funkce pro neúplnou aktualizaci slovníků?

tedy částečný restart?

Ano ano. Stejně jako možnost tam nastavit pole MySQL, tedy aktualizovat poté, aby se načetla pouze tato data, pokud je slovník velmi velký.

Velmi zajímavá funkce. A zdá se mi, že to někdo navrhl v našem chatu. Možná jsi to byl dokonce ty.

Myslím, že ne.

Skvělé, teď se ukazuje, že dvě žádosti. A můžete to začít dělat pomalu. Ale chci vás hned varovat, že implementace této funkce je docela jednoduchá. To znamená, že teoreticky stačí zapsat číslo verze do tabulky a pak napsat: verze je menší než taková a taková. A to znamená, že to s největší pravděpodobností nabídneme nadšencům. Jste nadšenec?

Ano, ale bohužel ne v C++.

Umí vaši kolegové psát v C++?

Někoho najdu.

Skvělý*.

* funkce byla přidána dva měsíce po zprávě - byla vyvinuta autorem otázky a předložena jeho pull request.

Děkujeme!

Ahoj! Díky za zprávu! Zmínil jste, že ClickHouse velmi dobře spotřebovává všechny zdroje, které má k dispozici. A řečník vedle Luxofta o svém rozhodnutí hovořil pro ruskou poštu. ClickHouse se jim prý velmi líbil, ale nepoužili ho místo hlavního konkurenta právě proto, že sežral celý procesor. A nemohli to vměstnat do své architektury, do svého ZooKeepera s doky. Je možné nějak omezit ClickHouse, aby nespotřeboval vše, co se mu dostane k dispozici?

Ano, je to možné a velmi snadné. Pokud chcete spotřebovat méně jader, tak stačí napsat set max_threads = 1. A to je vše, požadavek provede v jednom jádru. Navíc můžete zadat různá nastavení pro různé uživatele. Takže žádný problém. A řekněte svým kolegům z Luxoftu, že není dobře, že toto nastavení nenašli v dokumentaci.

Alexey, ahoj! Chtěl bych se zeptat na tuto otázku. Není to poprvé, co slyším, že mnoho lidí začíná používat ClickHouse jako úložiště protokolů. Ve zprávě jste řekli, že to nedělejte, to znamená, že nepotřebujete ukládat dlouhé řádky. Co si o tom myslíš?

Za prvé, protokoly obvykle nejsou dlouhé řady. Existují samozřejmě výjimky. Například nějaká služba napsaná v Javě vyvolá výjimku, zaprotokoluje se. A tak v nekonečné smyčce a nedostatku místa na pevném disku. Řešení je velmi jednoduché. Pokud jsou čáry velmi dlouhé, ořízněte je. Co znamená dlouhý? Desítky kilobajtů jsou špatné *.

* v posledních verzích ClickHouse je povolena "adaptivní indexová granularita", která z větší části odstraňuje problém s ukládáním dlouhých řetězců.

Je kilobajt normální?

Za normálních okolností.

Ahoj! Díky za zprávu! Už jsem se na to v chatu ptal, ale nepamatuji si, jestli jsem dostal odpověď. Existuje nějaký plán na rozšíření sekce WITH způsobem CTE?

Ještě ne. Část WITH je poněkud frivolní. Je to pro nás jako malá funkce.

Chápu. Děkuji!

Díky za zprávu! Velmi zajímavé! globální otázka. Plánuje se, třeba formou jakýchsi pahýlů, úprava mazání dat?

Nezbytně. Toto je náš první úkol v naší frontě. Nyní aktivně přemýšlíme, jak vše udělat správně. A měli byste začít mačkat klávesnici*.

* stiskl tlačítka na klávesnici a vše bylo hotovo.

Ovlivní to nějak výkon systému nebo ne? Bude vložka tak rychlá jako nyní?

Možná samotné mazání, samotné aktualizace budou velmi těžké, ale to nijak neovlivní výkon selectů a výkon insertů.

A ještě jeden malý dotaz. Na prezentaci jste mluvili o primárním klíči. V souladu s tím máme rozdělení, které je standardně měsíční, že? A když nastavíme časové období, které se vejde do měsíce, pak čteme pouze tento oddíl, že?

Ano.

Otázka. Pokud nemůžeme vybrat žádný primární klíč, je správné to udělat přesně podle pole „Datum“, aby na pozadí došlo k menší restrukturalizaci těchto dat, aby se vešly uspořádaněji? Pokud nemáte dotazy na rozsah a nemůžete ani vybrat žádný primární klíč, vyplatí se vložit datum do primárního klíče?

Ano.

Možná má smysl dát do primárního klíče pole, podle kterého se budou data lépe komprimovat, pokud budou řazena podle tohoto pole. Například ID uživatele. Uživatel například přejde na stejnou stránku. V tomto případě zadejte ID uživatele a čas. A pak budou vaše data lépe komprimována. Pokud jde o datum, pokud opravdu nemáte a nikdy nemáte dotazy na rozsah na data, nemůžete datum vložit do primárního klíče.

Dobře, děkuji mnohokrát!

Zdroj: www.habr.com

Přidat komentář