
Mimo że danych jest teraz wiele prawie wszędzie, analityczne bazy danych wciąż są dość egzotyczne. Są słabo znane i jeszcze gorzej umieją być efektywnie wykorzystywane. Wiele osób wciąż "je kaktusa" z MySQL lub PostgreSQL, które zostały zaprojektowane do innych scenariuszy, męczy się z NoSQL lub przepłaca za komercyjne rozwiązania. ClickHouse zmienia zasady gry i znacząco obniża próg wejścia w świat analitycznych DBMS.
Prezentacja z BackEnd Conf 2018 roku, opublikowana za zgodą prelegenta.


Kim jestem i dlaczego opowiadam o ClickHouse? Jestem dyrektorem ds. rozwoju w firmie LifeStreet, która korzysta z ClickHouse. Ponadto jestem założycielem Altinity. To partner Yandexu, który promuje ClickHouse i pomaga Yandexowi uczynić ClickHouse bardziej udanym. Również chętnie dzielę się wiedzą o ClickHouse.

I jeszcze nie jestem bratem Piotra Zajcewa. Często o to pytają. Nie, nie jesteśmy braćmi.

„Wszyscy wiedzą”, że ClickHouse:
- Jest bardzo szybki,
- Jest bardzo wygodny,
- Jest używany w Yandexie.
Nieco mniej wiadomo, w jakich firmach i jak jest wykorzystywany.

Opowiem wam, do czego, gdzie i jak ClickHouse jest używany, poza Yandexem.
Opowiem, jak konkretne zadania są rozwiązywane za pomocą ClickHouse w różnych firmach, jakie narzędzia ClickHouse możecie użyć do swoich zadań i jak zostały one wykorzystane w różnych firmach.
Wybrałem trzy przykłady, które pokazują ClickHouse z różnych perspektyw. Myślę, że to będzie interesujące.

Pierwsze pytanie: "Po co potrzebny jest ClickHouse?". Wydaje się, że pytanie jest dość oczywiste, ale odpowiedzi jest więcej niż jedna.

- Pierwsza odpowiedź – z powodu wydajności. ClickHouse jest bardzo szybki. Analizy na ClickHouse również są bardzo szybkie. Często można go używać tam, gdzie coś innego działa bardzo wolno lub bardzo źle.
- Druga odpowiedź – to koszt. A w pierwszej kolejności koszt skalowania. Na przykład Vertica – to świetna baza danych. Działa bardzo dobrze, jeśli nie masz zbyt wielu terabajtów danych. Ale gdy mowa o setkach terabajtów lub petabajtach, koszt licencji i wsparcia staje się dość znaczny. I to jest drogie. A ClickHouse jest darmowy.
- Trzecia odpowiedź to koszty operacyjne. To podejście jest nieco z innej perspektywy. RedShift to doskonały odpowiednik. W RedShift można bardzo szybko opracować rozwiązanie. Będzie działać dobrze, ale co godzinę, co dzień i co miesiąc będziesz płacić Amazonowi dość dużo, ponieważ jest to znacznie drogi serwis. Google BigQuery też. Jeśli ktoś go używał, to wie, że można uruchomić kilka zapytań i nagle otrzymać rachunek na setki dolarów.
W ClickHouse nie ma tych problemów.

Gdzie teraz używany jest ClickHouse? Oprócz Yandex, ClickHouse wykorzystywany jest w wielu różnych przedsiębiorstwach i firmach.
- Przede wszystkim jest to analiza aplikacji webowych, tzn. przypadek użycia, który pochodzi z Yandex.
- Wiele firm AdTech korzysta z ClickHouse.
- Liczne firmy, które muszą analizować operacyjne logi z różnych źródeł.
- Kilka firm wykorzystuje ClickHouse do monitorowania logów bezpieczeństwa. Ładują je do ClickHouse, tworzą raporty, uzyskują potrzebne im wyniki.
- Firmy zaczynają go używać w analizie finansowej, tzn. stopniowo duży biznes również zbliża się do ClickHouse.
- CloudFlare. Jeśli ktoś śledzi ClickHouse, to pewnie słyszał nazwę tej firmy. Jest jednym z kluczowych uczestników ze społeczności. I mają bardzo poważną instalację ClickHouse. Na przykład stworzyli Kafka Engine dla ClickHouse.
- Firmy telekomunikacyjne zaczęły z niego korzystać. Kilka firm używa ClickHouse albo jako proof of concept, albo już w produkcji.
- Jedna firma używa ClickHouse do monitorowania procesów produkcyjnych. Testują mikroprocesory, zapisują mnóstwo parametrów, około 2000 cech. A następnie analizują – dobra partia czy zła.
- Analiza blockchain. Jest taka rosyjska firma, jak Bloxy.info. To analiza sieci ethereum. Również zrobili to na ClickHouse.

Przy czym rozmiar nie ma znaczenia. Wiele firm korzysta z jednego małego serwera. I pozwala im to rozwiązać ich problemy. A jeszcze więcej firm korzysta z dużych klastrów z wielu serwerów lub dziesiątek serwerów.
A jeśli przyjrzeć się rekordom, to:
- Yandex: 500+ serwerów, codziennie przechowują tam 25 miliardów rekordów.
- LifeStreet: 60 serwerów, około 75 miliardów rekordów dziennie. Mniej serwerów, więcej rekordów niż w Yandex.
- CloudFlare: 36 serwerów, 200 miliardów zapisów dziennie, które przechowują. Mają jeszcze mniej serwerów i jeszcze więcej danych, które przechowują.
- Bloomberg: 102 serwera, około trylion zapisów dziennie. Rekordzista pod względem zapisów.

Geograficznie to również dużo. Ta mapa pokazuje heatmapę, gdzie ClickHouse jest używany na świecie. Szczególnie wyróżniają się Rosja, Chiny, Ameryka. Krajów europejskich jest mało. Można wyróżnić 4 klastry.
To jest analiza porównawcza, nie trzeba tu szukać absolutnych cyfr. To analiza odwiedzających, którzy czytają anglojęzyczne materiały na stronie Altinity, ponieważ nie ma tam materiałów w języku rosyjskim. I Rosja, Ukraina, Białoruś, czyli rosyjskojęzyczna część społeczności, to najliczniejsi użytkownicy. Następnie idą Stany Zjednoczone i Kanada. Bardzo szybko gonią Chiny. Jeszcze pół roku temu Chin prawie nie było, teraz Chiny już wyprzedziły Europę i dalej rosną. Stara Europa też nie pozostaje w tyle, a liderem w użyciu ClickHouse, co dziwne, jest Francja.

Dlaczego to wszystko opowiadam? Żeby pokazać, że ClickHouse staje się standardowym rozwiązaniem do analizy dużych danych i jest już szeroko stosowane. Jeśli go używasz, jesteś w dobrym nurcie. Jeśli jeszcze go nie używasz, nie musisz się martwić, że zostaniesz sam i nikt ci nie pomoże, ponieważ już wiele osób się tym zajmuje.

To są przykłady rzeczywistego użycia ClickHouse w kilku firmach.
- Pierwszy przykład to sieć reklamowa: migracja z Vertica na ClickHouse. Znam kilka firm, które przeszły z Vertica lub są w trakcie przechodzenia.
- Drugi przykład to transakcyjne przechowywanie danych w ClickHouse. To przykład zbudowany na antywzorcach. Wszystko, czego nie należy robić w ClickHouse według zaleceń deweloperów, zostało tu zrealizowane. I zostało to zrobione tak efektywnie, że działa. I działa znacznie lepiej niż typowe rozwiązanie transakcyjne.
- Trzeci przykład to rozproszone obliczenia w ClickHouse. Było pytanie o to, jak można zintegrować ClickHouse z ekosystemem Hadoop. Pokażę przykład, jak firma zrobiła w ClickHouse coś w rodzaju analogowego kontenera map reduce, śledząc lokalizację danych itd., aby rozwiązać bardzo nietrywialne zadanie.

- LifeStreet – to firma Ad Tech, która ma wszystkie technologie związane z siecią reklamową.
- Zajmuje się optymalizacją reklam, programatycznym licytowaniem.
- Wiele danych: około 10 miliardów zdarzeń dziennie. Przy tym zdarzenia mogą dzielić się na kilka podzdarzeń.
- Mnóstwo klientów korzysta z tych danych, przy czym to nie tylko ludzie, ale znacznie więcej – to różne algorytmy zajmujące się programmatic bidding.

Firma przeszła długą i wyboistą drogę. Opowiadałem o tym na HighLoad. Początkowo LifeStreet migrowała z MySQL (po krótkim okresie na Oracle) do Vertica. Można znaleźć opowieść na ten temat.
I wszystko wyglądało bardzo dobrze, ale szybko stało się jasne, że dane rosną, a Vertica staje się kosztowna. Dlatego szukano różnych alternatyw. Niektóre z nich zostały tu wymienione. Faktycznie przeprowadziliśmy proof of concept, a czasami testy wydajności prawie wszystkich baz danych, które były dostępne na rynku w latach 2013-2016 i mniej więcej pasowały funkcjonalnością. O części z nich również opowiadałem na HighLoad.

Zadanie polegało na migracji z Vertica w pierwszej kolejności, ponieważ dane rosły. Rosły eksponencjalnie przez kilka lat. Potem osiągnęły plateau, ale mimo to. Przewidując ten wzrost, wymagania biznesowe dotyczące objętości danych, na których trzeba prowadzić analitykę, wskazywały, że wkrótce rozmowy będą sięgać petabajtów. A za petabajty płaci się już bardzo drogo, dlatego szukano alternatywy, dokąd odejść.

Dokąd odejść? Długo nie było jasne, dokąd zmierzać, ponieważ z jednej strony są komercyjne bazy danych, które zdają się działać całkiem nieźle. Niektóre działają prawie tak samo dobrze jak Vertica, inne gorzej. Ale wszystkie są drogie, nie udało się znaleźć nic tańszego i lepszego.
Z drugiej strony są rozwiązania open source, których jest niewiele, tzn. do analityki można je policzyć na palcach. Są darmowe lub tanie, ale działają wolno. Często brakuje im niezbędnej i przydatnej funkcjonalności.
I do tej pory nic nie łączyło tego, co dobre w komercyjnych bazach danych, z tym wszystkim, co darmowe w open source – nie było takiego rozwiązania.

Nic nie było, dopóki niespodziewanie Yandex nie wyciągnął, jak królik z kapelusza, ClickHouse. I to było niespodziewane rozwiązanie, do tej pory zadają pytanie: „Po co?”, ale mimo to.

I już latem 2016 roku zaczęliśmy oglądać, czym jest ClickHouse. Okazało się, że czasami może być szybszy od Vertica. Testowaliśmy różne scenariusze na różnych zapytaniach. A jeśli zapytanie korzystało tylko z jednej tabeli, tzn. bez żadnych joinów, to ClickHouse był dwa razy szybszy od Vertica.
Nie leniłem się i spojrzałem na testy Yandexu kilka dni temu. Tam to samo: ClickHouse jest dwa razy szybszy od Vertica, dlatego często o tym mówią.
Ale jeśli w zapytaniach są joiny, to sytuacja staje się niejednoznaczna. ClickHouse może być dwa razy wolniejszy od Vertica. A jeśli trochę poprawimy zapytanie i przepiszemy je, to jest mniej więcej równe. Nieźle. I za darmo.

Otrzymując wyniki testów i przyglądając się temu z różnych perspektyw, LifeStreet przeszedł na ClickHouse.

To jest już rok 2016, przypominam. To było jak w anegdocie o myszach, które płakały i kłuły się, ale nadal jadły kaktusa. To było szczegółowo opisane, są na ten temat filmy itd.

Dlatego nie będę szczegółowo o tym opowiadał, powiem tylko o wynikach i kilku interesujących rzeczach, o których wtedy nie mówiłem.
Wyniki to:
- Udana migracja i od ponad roku system działa już w produkcji.
- Wydajność i elastyczność wzrosły. Z 10 miliardów rekordów, które mogliśmy sobie pozwolić przechowywać w ciągu dnia, a to przez krótki czas, LifeStreet przechowuje teraz 75 miliardów rekordów dziennie i może to robić przez 3 miesiące i dłużej. Jeśli liczyć w szczycie, to rejestruje to do miliona zdarzeń na sekundę. Ponad milion zapytań SQL dziennie trafia do tego systemu, głównie od różnych robotów.
- Mimo że dla ClickHouse zaczęto używać więcej serwerów niż dla Vertica, oszczędności uzyskano na sprzęcie, ponieważ w Vertica używano dość drogich dysków SAS. W ClickHouse używano SATA. A dlaczego? Ponieważ w Vertica insert jest synchronizowany. Synchronizacja wymaga, aby dyski zbytnio nie spowalniały, a także, aby sieć nie była zbyt powolna, co jest dość drogą operacją. A w ClickHouse insert jest asynchroniczny. Co więcej, zawsze można pisać lokalnie, nie ma dodatkowych kosztów, więc dane w ClickHouse można wstawiać znacznie szybciej niż w Vertica, nawet na nie najszybszych dyskach. A w przypadku odczytu jest to mniej więcej podobne. Odczyt na SATA, jeśli są w RAID, jest wystarczająco szybki.
- Nieograniczone licencją, tzn. 3 petabajty danych na 60 serwerów (20 serwerów to jedna replikacja) i 6 bilionów rekordów w faktach i agregatach. Nic podobnego nie mogło pozwolić sobie Vertica.

Teraz przechodzę do praktycznych aspektów w tym przykładzie.
- Pierwszym jest efektywna schematy. Od schemy zależy bardzo wiele.
- Drugim jest generowanie efektywnego SQL.

Typowe zapytanie OLAP to select. Część kolumn trafia do group by, część kolumn do funkcji agregujących. Jest where, które można przedstawić jako przekrój kostki. Całe group by można przedstawić jako projekcję. I dlatego nazywa się to wielowymiarową analizą danych.

Często modeluje się to w postaci schemy gwiazdy, gdy w centrum znajduje się fakt, a cechy tego faktu są rozmieszczone po bokach, w promieniach.

Z punktu widzenia projektowania fizycznego, tego jak to się układa w tabeli, zazwyczaj tworzy się znormalizowaną wersję. Możesz denormalizować, ale to jest kosztowne pod względem dysku i niezbyt efektywne w zapytaniach. Dlatego zazwyczaj robi się znormalizowaną wersję, tzn. tabelę faktów i wiele, wiele tabel wymiarowych.
Jednak w ClickHouse to działa słabo. Są dwa powody:
- Pierwszy – to dlatego, że ClickHouse nie ma zbyt dobrych joinów, to znaczy joiny są, ale są kiepskie. Na razie kiepskie.
- Drugi – to fakt, że tabele nie są aktualizowane. Zazwyczaj w tych tabelach, które otaczają schemat gwiazdy, trzeba coś zmieniać. Na przykład nazwa klienta, nazwa firmy itd. I to nie działa.
Istnieje wyjście z tej sytuacji w ClickHouse. Nawet dwa:
- Pierwsze – to użycie słowników. Słowniki zewnętrzne to to, co pomaga w 99% rozwiązać problem ze schemą gwiazdy, z aktualizacjami i innymi rzeczami.
- Drugie – to użycie tablic. Tablice również pomagają pozbyć się joinów i problemów z normalizacją.

- Nie potrzebujesz joinów.
- Aktualizowalne. Od marca 2018 roku pojawiła się niedokumentowana możliwość (w dokumentacji nie znajdziesz o tym) częściowego aktualizowania słowników, tzn. tych rekordów, które się zmieniły. Praktycznie – to jak tabela.
- Zawsze w pamięci, dlatego joiny ze słownikiem działają szybciej niż w przypadku, gdyby to była tabela, która leży na dysku, a jeszcze nie wiadomo, czy jest w cache, prawdopodobnie nie.

- Również nie potrzebujesz joinów.
- To kompaktowe przedstawienie 1 do wielu.
- I moim zdaniem, tablice są stworzone dla geeków. To funkcje lambda i inne.
To nie jest pusta deklaracja. To bardzo potężna funkcjonalność, która pozwala robić wiele rzeczy w sposób prosty i elegancki.

Typowe przykłady, które pomagają rozwiązywać zadania z użyciem tablic. Te przykłady są proste i wystarczająco ilustracyjne:
- Wyszukiwanie po tagach. Jeśli masz hashtagi i chcesz znaleźć jakieś wpisy po haśle.
- Wyszukiwanie po parach klucz-wartość. Również istnieją jakieś atrybuty z wartościami.
- Przechowywanie list kluczy, które musisz przetłumaczyć na coś innego.
Wszystkie te zadania można rozwiązać bez tablic. Tagi można zapisać w jednym wierszu i wybrać używając wyrażenia regularnego lub umieścić w osobnej tabeli, ale wtedy trzeba będzie robić złączenia (join).

A w ClickHouse nie trzeba nic robić, wystarczy opisać tablicę string dla hashtagów lub stworzyć zagnieżdżoną strukturę dla systemów typu klucz-wartość.
Zagnieżdżona struktura – może to nie jest najszczęśliwsza nazwa. To dwa tablice, które mają wspólną część w nazwie i niektóre powiązane cechy.
I wyszukiwanie po tagu jest bardzo proste. Istnieje funkcja has, która sprawdza, czy w tablicy znajduje się dany element. I to wszystko, znaleźliśmy wszystkie wpisy, które odnoszą się do naszej konferencji.
Wyszukiwanie po subid jest nieco bardziej skomplikowane. Musimy najpierw znaleźć indeks klucza, a potem wziąć element z tym indeksem i sprawdzić, czy ta wartość jest taka, jakiego potrzebujemy. Niemniej jednak to wciąż bardzo proste i kompaktowe.
Wyrażenie regularne, które chciałbyś napisać, gdybyś to wszystko przechowywał w jednym wierszu, byłoby po pierwsze, nieczytelne. A po drugie, działałoby znacznie dłużej niż dwa tablice.

Inny przykład. Masz tablicę, w której przechowujesz identyfikatory. I możesz je przetłumaczyć na imiona. Funkcja arrayMap. To typowa funkcja lambda. Przekazujesz do niej wyrażenia lambda. I dla każdego identyfikatora z słownika wyciąga wartość imienia.
Podobnie można zrealizować wyszukiwanie. Przekazujesz funkcję predykatu, która sprawdza, czemu odpowiadają elementy.

Te rzeczy znacznie upraszczają schemat i rozwiązują wiele problemów.
Ale następny problem, z którym się spotkaliśmy i o którym chciałbym wspomnieć, to efektywne zapytania.
- W ClickHouse nie ma planera zapytań. Wcale go nie ma.
- Niemniej jednak złożone zapytania muszą być planowane. W jakich przypadkach?
- Jeśli zapytanie zawiera wiele połączeń (join), które owijasz w podzapytania. I kolejność ich wykonania ma znaczenie.
- Po drugie, jeśli zapytanie jest rozproszone. Ponieważ w rozproszonym zapytaniu tylko najbliższe podzapytanie jest wykonywane w sposób rozproszony, a wszystko inne jest przekazywane na jeden serwer, do którego się podłączasz i wykonywane tam. Dlatego jeśli masz rozproszone zapytania z wieloma połączeniami (join), musisz wybierać kolejność.
Nawet w bardziej prostych przypadkach czasami warto wykonać pracę planisty i nieco przepisać zapytania.

Oto przykład. Po lewej stronie zapytanie, które pokazuje pięć najlepszych krajów. Wykonuje się to przez 2,5 sekundy, moim zdaniem. A po prawej stronie to samo zapytanie, ale nieco przepisane. Zamiast grupować według wiersza, zaczęliśmy grupować według klucza (int). I to jest szybsze. A potem połączyliśmy wyniki ze słownikiem. Zamiast 2,5 sekundy zapytanie wykonuje się w 1,5 sekundy. To dobrze.

Podobny przykład z przepisywaniem filtrów. Tutaj zapytanie dotyczące Rosji. Wykonuje się przez 5 sekund. Jeśli przepiszemy je w taki sposób, że będziemy porównywać ponownie nie wiersze, a liczby z jakimś zbiorem tych kluczy, które odnoszą się do Rosji, to będzie znacznie szybciej.

Jest wiele takich sztuczek. I pozwalają one znacznie przyspieszyć zapytania, które wydają się już działać szybko, lub, przeciwnie, działają wolno. Można je zrobić jeszcze szybciej.

- Maksymalne obciążenie w trybie rozproszonym.
- Sortowanie według minimalnych typów, jak to robiłem według intów.
- Jeśli są jakieś połączenia (join), słowniki, lepiej zrobić to na samym końcu, gdy masz już dane przynajmniej częściowo pogrupowane, wtedy operacja połączenia (join) lub wezwanie słownika będzie wywoływane mniej razy i będzie to szybsze.
- Zamiana filtrów.
Są jeszcze inne techniki, a nie tylko te, które zademonstrowałem. I wszystkie one czasami pozwalają znacznie przyspieszyć wykonanie zapytań.

Przechodzimy do następnego przykładu. Firma X z USA. Co ona robi?
Było zadanie:
- Offline powiązanie transakcji reklamy.
- Modelowanie różnych modeli powiązania.

Na czym polega scenariusz?
Zwykły użytkownik odwiedza stronę, na przykład 20 razy w miesiącu z różnych ogłoszeń lub po prostu czasami wraca bez żadnych ogłoszeń, ponieważ pamięta tę stronę. Ogląda różne produkty, wkłada je do koszyka, a potem je wyjmuje. A na końcu czegoś kupuje.
Słuszne pytania: "Komu należy zapłacić za reklamę, jeśli jest to konieczne?" oraz "Jaka reklama na niego wpłynęła, jeśli wpłynęła?". To znaczy, dlaczego kupił i jak sprawić, by ludzie podobni do niego również kupowali?
Aby rozwiązać ten problem, należy poprawnie powiązać zdarzenia, które występują na stronie internetowej, czyli jakoś je ze sobą połączyć. Następnie należy je przesłać do analizy do DWH. Na podstawie tej analizy rozwija się modele, którym i jakie reklamy pokazywać.

Transakcja reklamowa to zestaw powiązanych zdarzeń użytkownika, które zaczynają się od wyświetlenia ogłoszenia, następnie coś się dzieje, potem może być zakup, a następnie mogą wystąpić dodatkowe zakupy w ramach zakupu. Na przykład, jeśli to jest aplikacja mobilna lub gra mobilna, to zazwyczaj instalacja aplikacji jest darmowa, ale jeśli coś dalej się robi, mogą być potrzebne pieniądze. Im więcej osoba wyda w aplikacji, tym jest ona cenniejsza. Ale trzeba to wszystko powiązać.

Istnieje wiele modeli powiązań.
Najpopularniejsze z nich to:
- Ostatnia interakcja, gdzie interakcja to albo kliknięcie, albo wyświetlenie.
- Pierwsza interakcja, czyli pierwsza rzecz, która przyciągnęła osobę na stronę.
- Liniowa kombinacja – wszystkim równo.
- Wygasanie.
- I inne.

A jak to wszystko działało na początku? Był Runtime i Cassandra. Cassandra była używana jako pamięć transakcji, tzn. przechowywano w niej wszystkie powiązane transakcje. I gdy przychodzi jakieś zdarzenie do Runtime, na przykład wyświetlenie jakiejś strony czy coś innego, to wykonywano zapytanie do Cassandry – czy taka osoba istnieje, czy nie. Następnie pobierano transakcje, które się do niej odnoszą. I następowało powiązanie.
I jeśli miałeś szczęście, że w zapytaniu znajduje się id transakcji, to jest to łatwe. Ale zwykle nie ma szczęścia. Dlatego trzeba było znaleźć ostatnią transakcję lub transakcję z ostatnim kliknięciem itd.
I to wszystko działało bardzo dobrze, dopóki powiązanie opierało się na ostatnim kliknięciu. Ponieważ mamy, powiedzmy, 10 milionów kliknięć dziennie, co daje 300 milionów miesięcznie, jeśli ustawimy okno na miesiąc. A ponieważ w Cassandra wszystko musi być w pamięci, aby działało szybko, ponieważ wymagana jest szybka odpowiedź Runtime, to potrzebnych było około 10-15 serwerów.
A kiedy chcieliśmy powiązać transakcję z danymi wyświetleniami, to od razu zaczęło być mniej wesoło. Dlaczego? Widać, że trzeba przechowywać 30 razy więcej zdarzeń. A co za tym idzie, potrzebnych jest 30 razy więcej serwerów. I okazuje się, że to jakaś astronomiczna liczba. Utrzymanie do 500 serwerów, aby realizować powiązania, podczas gdy w Runtime serwerów jest znacznie mniej, to nie jest właściwa liczba. Zaczęliśmy myśleć, co zrobić.

I dotarliśmy do ClickHouse. A jak to zrobić w ClickHouse? Na pierwszy rzut oka wydaje się, że to zbiór antywzorów.
- Transakcja rośnie, podpinamy do niej coraz to nowe zdarzenia, czyli jest mutowalna, a ClickHouse nie radzi sobie z obiektami mutowalnymi.
- Kiedy odwiedzający przychodzi do nas, musimy wyciągnąć jego transakcje na podstawie klucza, jego visit id. To również jest zapytanie punktowe, a w ClickHouse tak się nie robi. Zwykle w ClickHouse wykonywane są duże skany, a tutaj musimy wyciągnąć kilka rekordów. Też antywzór.
- Ponadto transakcja była w JSON, ale nie chcieliśmy jej przepisywać, więc chcieliśmy przechowywać JSON w niestrukturalny sposób, a jeśli trzeba, to coś z niego wydobywać. I to również jest antywzór.
Czyli zestaw antywzorów.

Jednak udało się stworzyć system, który działał bardzo dobrze.
Co zrobiono? Pojawił się ClickHouse, do którego wgrywano logi podzielone na rekordy. Pojawiła się usługa atrybutów, która pozyskiwała logi z ClickHouse. Następnie dla każdego rekordu na podstawie visit id pozyskiwała transakcje, które mogły być jeszcze nieprzetworzone, oraz dodatkowo snapshoty, czyli już powiązane transakcje, a dokładniej wyniki wcześniejszej pracy. Na ich podstawie tworzyłem logikę, wybierałem odpowiednią transakcję, podłączałem nowe zdarzenia. Znowu zapisywałem w logu. Log wracał do ClickHouse, czyli to była stale cykliczna system. Poza tym trafiał do DWH, aby tam to analizować.
W tej formie to nie działało zbyt dobrze. Aby ułatwić ClickHouse, gdy pojawiało się zapytanie po ID wizyty, grupowano te zapytania w bloki po 1000-2000 ID wizyt i wyciągano dla 1000-2000 osób wszystkie transakcje. I wtedy to zadziałało.

Jeśli zajrzymy do wnętrza ClickHouse, to są tam tylko 3 główne tabele, które to obsługują.
Pierwsza tabela, do której trafiają logi, jest zalewana logami prawie bez przetwarzania.
Druga tabela. Przez widok zmaterializowany z tych logów wyciągano zdarzenia, które jeszcze nie były przypisane, czyli niezwiązane. I przez widok zmaterializowany z tych logów wyciągano transakcje do budowy zrzutu. To znaczy, specjalny widok zmaterializowany budował zrzut, a dokładnie ostatni zgromadzony stan transakcji.

Tutaj jest napisany tekst w SQL. Chciałbym skomentować kilka ważnych rzeczy w tym kontekście.
Pierwsza ważna rzecz – to możliwość wyciągania kolumn z json w ClickHouse. To znaczy, w ClickHouse istnieją pewne metody pracy z json. Są one bardzo, bardzo prymitywne.
visitParamExtractInt pozwala na wyciąganie atrybutów z json, to znaczy pierwsze trafienie działa. Dzięki temu można wyciągnąć ID transakcji lub ID wizyty. To jest jedno.
Po drugie – tutaj użyto sprytnego pola zmaterializowanego. Co to oznacza? Oznacza to, że nie można go wkładać do tabeli, to znaczy, że nie jest wstawiane, jest obliczane i przechowywane podczas wstawiania. Podczas wstawiania ClickHouse wykonuje pracę za ciebie. I już wyciągane jest z json to, co potem będzie potrzebne.
W tym przypadku widok zmaterializowany – to dla nieprzetworzonych wierszy. I właśnie wykorzystuje pierwszą tabelę z praktycznie surowymi logami. Co robi? Po pierwsze, zmienia sortowanie, to znaczy, że sortowanie teraz odbywa się według ID wizyty, ponieważ musimy szybko wyciągać transakcję konkretnej osoby.
Druga ważna rzecz – to index_granularity. Jeśli widziałeś MergeTree, to zwykle domyślnie ustawia się index_granularity na 8192. Co to oznacza? To jest parametr rzadkości indeksu. W ClickHouse indeks jest rzadki, nigdy nie indeksuje każdej rekord. Robi to co 8192. I to jest dobre, gdy potrzebujesz policzyć dużo danych, ale źle, gdy trochę, ponieważ pojawia się duży overhead. A jeśli zmniejszamy index granularity, to zmniejszamy overhead. Nie można go zmniejszyć do jedności, ponieważ może zabraknąć pamięci. Indeks zawsze przechowywany jest w pamięci.

A snapshot uses some other interesting features of ClickHouse.
Firstly, there is AggregatingMergeTree. The AggregatingMergeTree stores the argMax, i.e., this is the state of the transaction corresponding to the last timestamp. Transactions are continuously generated for a given visitor. In the most recent state of this transaction, we added an event, and we have a new state. It went back into ClickHouse. And through argMax in this materialized view, we can always obtain the current state.

- The binding is 'detached' from the Runtime.
- Up to 3 billion transactions are stored and processed monthly. This is an order of magnitude more than what was in Cassandra, i.e., in a typical transactional system.
- A cluster of 2x5 ClickHouse servers. 5 servers, and each server has a replica. This is even less than what was in Cassandra in order to perform click-based attribution, while here we use impression-based. That is, instead of increasing the number of servers by 30 times, they managed to reduce it.

And the last example is a financial company Y that analyzed the correlations of stock price changes.
And the task was as follows:
- There are approximately 5,000 stocks.
- Quotes are known every 100 milliseconds.
- Data has accumulated over 10 years. Obviously, some companies have more data, and some have less.
- In total, about 100 billion rows.
And it was necessary to calculate the correlation of changes.

Here are two stocks and their quotes. If one goes up and the other goes up, that is a positive correlation, i.e., one rises and the other rises. If one goes up, as at the end of the graph, and the other goes down, that is a negative correlation, i.e., when one rises, the other falls.
By analyzing these mutual changes, predictions can be made in the financial market.

But the task is complicated. So what is done for this? We have 100 billion records that contain: time, stock, and price. First, we need to calculate the runningDifference of the price algorithm 100 billion times. RunningDifference is a function in ClickHouse that sequentially computes the difference between two rows.
After that, we need to calculate the correlation, and moreover, the correlation must be calculated for each pair. For 5,000 stocks, there are 12.5 million pairs. And that’s a lot, i.e., we need to compute such a correlation function 12.5 times.
Jeśli ktoś zapomniał, to ͞x i ͞y to oczekiwana wartość dla próbki. Oznacza to, że trzeba nie tylko obliczyć pierwiastki i sumy, ale również wewnątrz tych sum obliczyć kolejne sumy. Należy wykonać mnóstwo obliczeń 12,5 miliona razy, a także pogrupować je według godzin. A godzin mamy też sporo. I trzeba to zrobić w ciągu 60 sekund. To żart.

Trzeba było się spieszyć, bo wszystko działało bardzo, bardzo wolno, zanim pojawił się ClickHouse.

Próbowali obliczać to na Hadoop, na Spark, na Greenplum. I wszystko to było bardzo wolne lub drogie. To znaczy, można było to jakoś obliczyć, ale potem było to kosztowne.

A potem pojawił się ClickHouse i wszystko stało się dużo lepsze.
Przypominam, mamy problem z lokalnością danych, dlatego nie możemy lokalizować korelacji. Nie możemy złożyć części danych na jednym serwerze, a części na drugim i policzyć; wszystkie dane muszą być wszędzie.
Co zrobili? Początkowo dane były lokalizowane. Na każdym z serwerów przechowywane są dane dotyczące wyceny określonego zestawu akcji. I nie zachodzą na siebie. Dlatego można jednocześnie i niezależnie obliczyć logReturn, wszystko to dzieje się równolegle i rozłożone.
Następnie postanowili te dane zmniejszyć, nie tracąc przy tym wyrazistości. Zmniejszyć za pomocą tablic, to znaczy dla każdego przedziału czasowego stworzyć tablicę akcji i tablicę cen. W ten sposób zajmują one znacznie mniej miejsca. I łatwiej się z nimi pracuje. To prawie równoległe operacje, to znaczy równolegle częściowo obliczamy i później zapisujemy na serwerze.
Po tym można to zreplikować. Literka 'r' oznacza, że te dane zreplikowaliśmy. To znaczy, że na wszystkich trzech serwerach są takie same dane – te tablice.
A następnie specjalnym skryptem z tego zestawu 12,5 miliona korelacji, które trzeba obliczyć, można stworzyć pakiety. To znaczy 2 500 zadań po 5 000 par korelacji. I to zadanie obliczać na konkretnym serwerze ClickHouse. Ma on wszystkie dane, ponieważ dane są identyczne i może je obliczać sekwencyjnie.

Jeszcze raz, jak to wygląda. Na początku mamy wszystkie dane w takiej strukturze: czas, akcje, cena. Następnie obliczyliśmy logReturn, czyli dane tej samej struktury, tylko zamiast ceny mamy już logReturn. Potem przekształciliśmy je, co dało nam czas oraz groupArray dla akcji i cen. Zreplikowaliśmy. Po tym wygenerowaliśmy mnóstwo zadań i wrzuciliśmy je do ClickHouse, aby to przetworzył. I to działa.

Na proof of concept zadanie to była podzadanie, czyli wzięliśmy mniej danych. I to wszystko na trzech serwerach.
Pierwsze dwa etapy: obliczanie Log_return i owinięcie w tablice zajęły około godziny każda.
A obliczanie korelacji zajęło gdzieś 50 godzin. Ale 50 godzin to mało, ponieważ wcześniej trwało to tygodniami. To był wielki sukces. I jeśli policzyć, to na tym klastrze wszystko było obliczane 70 razy na sekundę.
Ale najważniejsze jest to, że ten system praktycznie nie ma wąskich gardeł, co oznacza, że skalowanie przebiega prawie liniowo. I to zostało zweryfikowane. Skutecznie go skalowali.

- Poprawna schemat to połowa sukcesu. A poprawne schematy to wykorzystanie wszystkich potrzebnych technologii ClickHouse.
- Summing/AggregatingMergeTrees to technologie, które pozwalają agregować lub obliczać stan snapshot jako szczególny przypadek. I to znacząco upraszcza wiele spraw.
- Materialized Views pozwalają obejść ograniczenie jednego indeksu. Może nie do końca jasno to wyjaśniłem, ale gdy ładowaliśmy logi, surowe logi były w tabeli z jednym indeksem, a logi atrybutów były w innej tabeli, to znaczy te same dane, tylko przefiltrowane, ale indeks był zupełnie inny. Wydają się to być te same dane, ale różni się sortowanie. I Materialized Views pozwala, jeśli jest to potrzebne, obejść to ograniczenie ClickHouse.
- Zmniejszaj granularity indeksu dla punktowych zapytań.
- I rozdzielaj dane mądrze, staraj się maksymalnie lokalizować dane wewnątrz serwera. I staraj się, aby zapytania również korzystały z lokalizacji tam, gdzie to możliwe.

Podsumowując tę krótką prezentację, można stwierdzić, że ClickHouse z powodzeniem zajął miejsce zarówno w komercyjnych bazach danych, jak i w bazach open source, tj. w analizie danych. Doskonale wpasował się w ten krajobraz. Co więcej, powoli zaczyna wypierać innych, ponieważ gdy mamy ClickHouse, nie potrzebujemy InfiniDB. Może Vertica wkrótce stanie się zbędna, jeśli zapewnią odpowiednie wsparcie dla SQL. Polecam korzystać!

—Dziękuję za referat! Bardzo interesujące! Czy były jakieś porównania z Apache Phoenix?
-Nie, nie słyszałem, aby ktoś porównywał. My i Yandex staramy się śledzić wszystkie porównania ClickHouse z różnymi bazami danych. Ponieważ jeśli przypadkiem coś okazuje się szybsze niż ClickHouse, to Aleksey Milovidov nie może spać w nocy i szybko stara się go przyspieszyć. Nie słyszałem o takim porównaniu.
(Aleksey Milovidov) Apache Phoenix to silnik SQL na Hbase. Hbase jest głównie przeznaczone do scenariuszy pracy typu key-value. Tam w każdym wierszu może być dowolna liczba kolumn z dowolnymi nazwami. Można to powiedzieć o takich systemach jak Hbase, Cassandra. Na nich trudne zapytania analityczne nie będą działać poprawnie. Lub możesz pomyśleć, że działają normalnie, jeśli nie miałeś żadnego doświadczenia z ClickHouse.
Dziękuję
Dzień dobry! Już od dłuższego czasu interesuję się tym tematem, ponieważ mam system analityczny. Ale kiedy patrzę na ClickHouse, mam wrażenie, że ClickHouse bardzo dobrze nadaje się do analizy zdarzeń, danych mutowalnych. A jeśli muszę analizować wiele danych biznesowych z dużą ilością tabel, to ClickHouse, o ile rozumiem, niezbyt mi pasuje? Szczególnie, jeśli się zmieniają. Czy to prawda, czy są przykłady, które mogą to obalić?
To prawda. I to dotyczy większości specjalistycznych baz danych analitycznych. Są one dostosowane do tego, że występuje jedna lub kilka dużych tabel, które są zmienne, oraz wiele małych, które zmieniają się powoli. Tzn. ClickHouse nie jest jak Oracle, gdzie można wrzucić wszystko i budować bardzo skomplikowane zapytania. Aby efektywnie korzystać z ClickHouse, należy stworzyć schemat w taki sposób, aby dobrze funkcjonował w ClickHouse. Tzn. unikać nadmiernej normalizacji, używać słowników, starać się ograniczyć długie powiązania. I jeśli schemat zostanie w ten sposób skonstruowany, to podobne zadania biznesowe w ClickHouse mogą być rozwiązywane znacznie efektywniej niż w tradycyjnej bazie danych relacyjnej.
Dziękuję za prezentację! Mam pytanie dotyczące ostatniego przypadku finansowego. Mieli analizę. Należało porównać, jak zmieniają się wartości. Rozumiem, że system został zbudowany właśnie pod tę analizę? Jeśli na przykład jutro potrzebny będzie im inny raport na podstawie tych danych, czy muszą budować schemat od nowa i ładować dane? Tzn. czy potrzebna jest jakaś wstępna obróbka, aby uzyskać zapytanie?
Oczywiście, to użycie ClickHouse do całkowicie konkretnego zadania. Tradycyjnie mogłoby być ono rozwiązane w ramach Hadoop. Dla Hadoop to idealne zadanie. Ale na Hadoop jest to bardzo wolne. Moim celem jest pokazanie, że w ClickHouse można rozwiązywać zadania, które zazwyczaj są realizowane przy użyciu całkowicie innych środków, ale można to zrobić znacznie efektywniej. To jest dostosowane do konkretnego zadania. Jest oczywiste, że jeśli pojawi się coś podobnego, można je rozwiązać w podobny sposób.
Rozumiem. Powiedziałeś, że przetwarzano 50 godzin. Czy to od samego początku, gdy załadowano dane, czy od momentu uzyskania rezultatów?
Tak, tak.
Dobrze, bardzo dziękuję.
To jest na klastrze 3-serwerowym.
Witam! Dziękuję za prezentację! Wszystko jest bardzo interesujące. Chciałem zapytać nieco nie o funkcjonalność, a o użycie ClickHouse z punktu widzenia stabilności. Czy mieliście jakieś problemy, czy musieliście dokonywać przywrócenia? Jak w tym przypadku zachowuje się ClickHouse? Czy zdarzały się sytuacje, w których również replika się wyłączała? My na przykład mieliśmy problem z ClickHouse, gdy jednak przekraczał swój limit i padał.
Oczywiście, nie ma idealnych systemów. ClickHouse również ma swoje problemy. Ale czy słyszałeś o tym, że Yandex.Metrica długo nie działała? Prawdopodobnie nie. Działa niezawodnie gdzieś od 2012-2013 roku na ClickHouse. Można również mówić o moim doświadczeniu. Nigdy nie mieliśmy całkowitych awarii. Mogły zdarzać się jakieś częściowe problemy, ale nigdy nie były one na tyle krytyczne, żeby poważnie wpłynąć na biznes. Takiego sytuacji nigdy nie było. ClickHouse jest wystarczająco niezawodny i nie pada przypadkowo. Nie ma co się tym martwić. To nie jest surowy produkt. Potwierdza to wiele firm.
Witam! Powiedziałeś, że trzeba od razu dobrze przemyśleć schemat danych. A co, jeśli to się jednak stało? Dane napływają bez końca. Mija pół roku, a ja rozumiem, że tak dalej żyć się nie da, muszę przetworzyć dane i coś z nimi zrobić.
To oczywiście zależy od twojego systemu. Istnieje kilka sposobów, aby zrobić to praktycznie bez przestojów. Na przykład, możesz stworzyć Materialized View, w którym skonstruujesz inną strukturę danych, jeśli można ją jednoznacznie zmapować. To znaczy, jeśli dopuszcza mapowanie przy pomocy ClickHouse, to znaczy extract niektóre rzeczy, zmienić klucz główny, zmienić partycjonowanie, to można zrobić Materialized View. Tam przepiszesz swoje stare dane, nowe będą zapisywane automatycznie. A potem po prostu przełączysz się na używanie Materialized View, a następnie przestawisz zapis i usuniesz starą tabelę. To sposób bez przerwy.
Dziękujemy.
Źródło: habr.com
