Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

Ponieważ ClickHouse jest wyspecjalizowanym systemem, ważne jest, aby przy jego użyciu uwzględnić cechy jego architektury. W tej prezentacji Aleksiej opowie o typowych błędach podczas korzystania z ClickHouse, które mogą prowadzić do niewłaściwej pracy. Na przykładach praktycznych pokaże, jak wybór konkretnego schematu przetwarzania danych może znacząco wpłynąć na wydajność.

Cześć wszystkim! Nazywam się Aleksiej, zajmuję się ClickHouse.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

Po pierwsze, od razu chciałbym Was uspokoić, że dzisiaj nie będę mówił, czym jest ClickHouse. Szczerze mówiąc, już mi się to znudziło. Za każdym razem to powtarzam. I pewnie wszyscy już to wiedzą.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

Zamiast tego opowiem, jakie są możliwe pułapki, czyli jak można niewłaściwie wykorzystać ClickHouse. Tak naprawdę nie ma się czego bać, ponieważ rozwijamy ClickHouse jako system, który jest prosty, wygodny i działa od razu po zainstalowaniu. Wystarczy zainstalować i wszystko, żadnych problemów.

Jednak warto mieć na uwadze, że jest to system wyspecjalizowany i łatwo można natknąć się na nietypowy scenariusz użycia, który wyprowadzi ten system z jego strefy komfortu.

A więc, jakie pułapki są dostępne? Głównie będę mówił o oczywistych rzeczach. Wszystkim wszystko wydaje się oczywiste, wszyscy rozumieją i mogą cieszyć się, że są tacy mądrzy, a ci, którzy nie rozumieją, dowiedzą się czegoś nowego.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

Pierwszy najprostszy przykład, który niestety często się zdarza, to duża liczba insercji z małymi paczkami, czyli dużą ilością małych insercji.

Jeśli spojrzeć, jak ClickHouse wykonuje insercję, to w jednym zapytaniu można wysłać nawet strumień danych o rozmiarze terabajta. To nie stanowi problemu.

Zobaczmy, jaka będzie typowa wydajność. Na przykład mamy tabelę z danymi Yandex.Metriki. Hitów. 105 kolumn. 700 bajtów w postaci nieskompresowanej. Będziemy wstawiać, jak należy, paczkami po milion wierszy.

Wstawiamy do tabeli MergeTree, otrzymujemy pół miliona wierszy na sekundę. Świetnie. W tabeli replikowanej będzie to trochę mniej, około 400 000 wierszy na sekundę.

A jeśli włączymy kworumową insercję, to wynosi to nieco mniej, ale nadal przyzwoita wydajność, 250 000 wierszy na sekundę. Kworumowa insercja to niedokumentowana możliwość w ClickHouse*.

* stan na 2020 rok, już udokumentowana.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

Co się stanie, jeśli wszystko będzie robione źle? Wstawiamy jedno pole na raz do tabeli MergeTree i uzyskujemy 59 wierszy na sekundę. To jest 10 000 razy wolniej. W ReplicatedMergeTree – 6 wierszy na sekundę. A jeśli dodatkowo włączy się quorum, to wychodzi 2 wiersze na sekundę. Moim zdaniem to jakiś totalny sąd. Jak można tak zwalniać? Nawet na moim T-shircie jest napisane, że ClickHouse nie powinien zwalniać. A jednak czasami się zdarza.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

W rzeczywistości to nasza wada. Moglibyśmy to zrobić tak, aby wszystko działało poprawnie, ale tego nie zrobiliśmy. A nie zrobiliśmy tego, ponieważ w naszym scenariuszu to nie było wymagane. Mieliśmy już wsady. Po prostu przychodziły do nas wsady i wszystko działało bez problemów. Wstawiamy i wszystko działa normalnie. Ale oczywiście mogą wystąpić różne scenariusze. Na przykład, gdy masz wiele serwerów, na których generowane są dane. I wstawiają dane niezbyt często, ale nadal występują częste wstawienia. I jakoś trzeba tego uniknąć.

Z technicznego punktu widzenia chodzi o to, że gdy wykonujesz insert w ClickHouse, dane nie trafiają do żadnego memtable. Nawet nie mamy prawdziwego log structure MergeTree, tylko po prostu MergeTree, ponieważ nie ma ani loga, ani memTable. Po prostu od razu zapisujemy dane w systemie plików, już rozłożone na kolumny. I jeśli masz 100 kolumn, to musisz zapisać więcej niż 200 plików w osobnym katalogu. To wszystko jest dość uciążliwe.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

Pojawia się pytanie: „Jak to zrobić prawidłowo?”, jeśli sytuacja jest taka, że musisz w jakiś sposób zapisywać dane w ClickHouse.

Sposób 1. To najprostszy sposób. Użyj jakiejś rozproszonej kolejki. Na przykład, Kafka. Po prostu wyciągasz dane z Kafka, batchujesz co sekundę. I wszystko będzie w porządku, zapisujesz i wszystko działa normalnie.

Wady są takie, że Kafka to kolejny skomplikowany system rozproszony. Rozumiem, jeśli w twojej firmie już jest Kafka. To dobrze, to wygodne. Ale jeśli jej nie ma, to warto trzy razy się zastanowić, zanim wciągniesz kolejny system rozproszony do swojego projektu. Dlatego warto rozważyć alternatywy.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

Metoda 2. Oto taka oldschoolowa alternatywa, która jest bardzo prosta. Macie jakiś serwer, który generuje wasze logi. I on po prostu zapisuje wasze logi do pliku. Co sekundę, na przykład, zmieniamy nazwę pliku, tworzymy nowy. A oddzielny skrypt, albo według crona, albo jakiś daemon pobiera najstarszy plik i zapisuje do ClickHouse. Jeśli zapisujecie logi co sekundę, to wszystko będzie działać doskonale.

Jednak wadą tego rozwiązania jest to, że jeśli wasz serwer, na którym generowane są logi, gdzieś zniknie, to także dane znikną.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

Metoda 3. Jest jeszcze jeden ciekawy sposób, który nie wymaga plików tymczasowych. Na przykład, macie jakąś reklamową pętlę lub inny interesujący daemon, który generuje dane. Możecie gromadzić paczkę danych bezpośrednio w pamięci operacyjnej, w buforze. I gdy upłynie wystarczająca ilość czasu, odkładacie ten bufor na bok, tworzycie nowy, a w oddzielnym wątku to, co już się zgromadziło, wstawiajcie do ClickHouse.

Z drugiej strony dane również znikają przy kill -9. Jeśli wasz serwer się zawiesi, to te dane stracicie. I jeszcze problem polega na tym, że jeśli nie moglibyście zapisać do bazy, to dane gromadzą się w pamięci operacyjnej. I albo skończy się pamięć operacyjna, albo po prostu stracicie dane.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

Metoda 4. Jeszcze jeden ciekawy sposób. Macie jakiś proces serwerowy. I może on wysyłać dane do ClickHouse od razu, ale robi to w jednym połączeniu. Na przykład, wysyła http-zapytanie z transfer-encoding: chunked z insert'em. I generuje kawałki już niezbyt rzadko, można wysyłać każdą linijkę, chociaż będzie overhead na ramki tych danych.

Jednak w każdym razie dane będą wysyłane do ClickHouse od razu. A ClickHouse sam je zbuforuje.

Ale również pojawiają się problemy. Teraz stracicie dane, w tym przypadku, gdy wasz proces zakończy działanie, a jeśli proces ClickHouse się zawiesi, ponieważ to będzie nieukończony insert. A w ClickHouse inserts są atomowe do pewnego określonego progu w liczbie wierszy. W zasadzie to ciekawy sposób. Można go również używać.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

Metoda 5. Oto kolejny interesujący sposób. To serwer do batchowania danych stworzony przez społeczność. Sam go nie sprawdzałem, więc niczego nie mogę zagwarantować. Zresztą, dla samego ClickHouse również nie ma żadnych gwarancji. To też open source, ale z drugiej strony mogliście przyzwyczaić się do pewnego standardu jakości, który staramy się zapewniać. Co do tego rozwiązania – nie wiem, zajrzyjcie na GitHub, sprawdźcie kod. Może napisano coś sensownego.

* według stanu na 2020 rok, należy również uwzględnić w rozważaniach KittenHouse.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

Metoda 6. Innym sposobem jest wykorzystanie tabel buforowych. Zaletą tego rozwiązania jest to, że bardzo łatwo można zacząć z niego korzystać. Tworzysz tabelę buforową i wstawiasz do niej dane.

A wadą jest to, że problem nie jest rozwiązywany w całości. Jeśli przy wstawianiu typu MergeTree musisz grupować dane po jednym batchu na sekundę, to przy wstawianiu do tabeli buforowej musisz grupować co najmniej do kilku tysięcy na sekundę. Jeśli będzie więcej niż 10 000 na sekundę, to i tak będzie źle. Natomiast jeśli wstawiasz w partiach, to widzieliście, że można osiągnąć setki tysięcy wierszy na sekundę. A to już na dosyć ciężkich danych.

I również tabele buforowe nie mają loga. Jeśli z twoim serwerem coś jest nie tak, dane zostaną utracone.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

A jako bonus, niedawno w ClickHouse pojawiła się możliwość pobierania danych z Kafka. Istnieje silnik tabel – Kafka. Po prostu go tworzysz. I można na niego nałożyć materializowane widoki. W takim przypadku sam będzie wyciągał dane z Kafka i wstawiał je do odpowiednich tabel.

I szczególnie cieszy w tej funkcjonalności to, że nie my ją stworzyliśmy. To funkcja społeczności. I kiedy mówię 'funkcja społeczności', mówię to bez żadnego pogardzenia. Kod czytaliśmy, robiliśmy przeglądy, powinno działać poprawnie.

* według stanu na 2020 rok, pojawiło się podobne wsparcie dla RabbitMQ.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

Co jeszcze może być niewygodne lub zaskakujące przy wstawianiu danych? Jeśli robisz zapytanie insert values i w values wpisujesz jakieś wyrażenia obliczeniowe. Na przykład, now() – to również jest wyrażenie obliczeniowe. W takim przypadku ClickHouse musi uruchomić interpreter tych wyrażeń dla każdego wiersza, co znacznie obniża wydajność. Lepiej tego unikać.

* aktualnie problem jest całkowicie rozwiązany, a regresji wydajności przy używaniu wyrażeń w VALUES już nie ma.

Inny przykład, kiedy mogą wystąpić pewne problemy, to kiedy w jednym batchu dane dotyczą wielu partycji. Domyślnie w ClickHouse partycje są według miesięcy. Jeśli wstawiasz batch z milionem wierszy, a dane sięgają kilku lat, to pojawi się kilka dziesiątek partycji. I to odpowiada temu, że będą batchy o wielkości kilkadziesiąt razy mniejszej, ponieważ wewnątrz zawsze są najpierw dzielone według partycji.

* niedawno w ClickHouse w trybie eksperymentalnym dodano wsparcie dla kompaktowego formatu bloków oraz bloków w pamięci operacyjnej z logowaniem do przodu, co prawie całkowicie rozwiązuje problem.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

Teraz przyjrzyjmy się drugiemu rodzajowi problemu – typizacji danych.

Typizacja danych może być ścisła lub tekstowa. Tekstowa to wtedy, gdy po prostu zadeklarujesz, że wszystkie pola są typu string. To jest niewłaściwe. Nie należy tego robić.

Zrozummy, jak to zrobić poprawnie w przypadkach, kiedy chcemy powiedzieć, że jakieś pole to string, i niech ClickHouse się tym zajmie, a ja się nie będę przejmował. Mimo to warto podjąć pewne wysiłki.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

Na przykład mamy adres IP. W jednym przypadku zachowaliśmy go jako string. Na przykład 192.168.1.1. A w innym przypadku będzie to liczba typu UInt32*. 32 bity wystarczą dla adresu IPv4.

Po pierwsze, jak nie jest dziwne, dane skompresują się mniej więcej tak samo. Będzie jakaś różnica, oczywiście, ale nie tak duża. Więc nie ma większych problemów z wejściem/wyjściem dyskowym.

Ale jest znacząca różnica w czasie procesora i czasie wykonywania zapytania.

Obliczając liczbę unikalnych adresów IP, jeśli są one przechowywane jako liczby, otrzymujemy 137 milionów wierszy na sekundę. Jeśli to samo w postaci stringów, to 37 milionów wierszy na sekundę. Nie wiem, dlaczego tak się stało. Sam wykonywałem te zapytania. Mimo to jest to około 4 razy wolniej.

A jeśli policzyć różnicę w miejscu na dysku, to również jest różnica. I różnica wynosi około ćwierci, ponieważ unikalnych adresów IP jest wystarczająco dużo. I gdyby tutaj były wiersze z małą ilością różnych wartości, to spokojnie skompresowałyby się w słownik do mniej więcej tej samej objętości.

A fourfold difference in travel time isn't something to overlook. You may not care, but when I see such a discrepancy, it makes me sad.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

Let’s consider different scenarios.

1. One scenario where you have a few unique values. In this case, we use a simple practice that you probably know and can apply to any DBMS. This principle makes sense not only for ClickHouse. You simply save numerical identifiers in the database. Converting them to strings and back can be done on your application side.

For example, you have a region. You try to save it as a string. It could say: Moscow and MO. When I see 'Moscow', that’s fine, but when it includes 'MO', it feels quite disheartening. That's quite a few bytes.

Instead, we simply save the number Ulnt32 and 250. We have 250 in Yandex, and you might have it differently. Just to mention, ClickHouse has built-in capabilities for working with geo databases. You write up a reference list with regions, including hierarchical ones, meaning it will have Moscow, MO, and everything else you need. And you can convert at the query level.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

The second option is quite similar but already supports it within ClickHouse. This is the Enum data type. You simply list all the values you need within Enum. For example, the device type, where you would write: desktop, mobile, tablet, TV. Just 4 options.

The downside is that you need to alter periodically. You add just one option, and you do an alter table. In fact, alter table in ClickHouse is free. It is especially free for Enum because the data on disk doesn't change. Nevertheless, alter acquires a lock* on the table and must wait for all selects to finish. Only after that does the alter execute, which means there are still some inconveniences.

* In recent versions of ClickHouse, ALTER is fully non-blocking.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

Another quite unique option for ClickHouse is the connection of external dictionaries. You can write numbers into ClickHouse while keeping your directories in any system you prefer. For instance, you can use MySQL, Mongo, Postgres. You can even build your microservice that will deliver this data over HTTP. At the ClickHouse level, you write a function that converts these numbers into strings.

To jest wyspecjalizowany, ale bardzo efektywny sposób na wykonanie połączenia z zewnętrzną tabelą. Istnieją dwa warianty. W jednym z nich dane będą w pełni zbuforowane, całkowicie obecne w pamięci operacyjnej i aktualizowane z pewną okresowością. W drugim wariancie, jeśli dane nie mieszczą się w pamięci, można je częściowo zbuforować.

Oto przykład. Jest Yandex.Direct. I tam jest kampania reklamowa oraz banery. Kampanii reklamowych jest prawdopodobnie kilkanaście milionów. W dużej mierze mieszczą się one w pamięci operacyjnej. A banerów – są miliardy, one się nie mieszczą. Dlatego korzystamy z buforowanego słownika z MySQL.

Jedynym problemem jest to, że buforowany słownik będzie działał poprawnie, jeśli współczynnik trafień wynosi blisko 100%. Jeśli jest mniejszy, to przy przetwarzaniu zapytań na każdą partię danych trzeba będzie rzeczywiście pobrać brakujące klucze i zaciągać dane z MySQL. W przypadku ClickHouse mogę się jeszcze upewnić, że tak, nie spowalnia, natomiast o innych systemach nie będę mówić.

A jako bonus, słowniki to bardzo prosty sposób na aktualizację danych w ClickHouse z datą wsteczną. To znaczy, że jeśli mieliście raport dotyczący kampanii reklamowych, a użytkownik po prostu zmienił kampanię reklamową, to we wszystkich starych danych, we wszystkich raportach te dane też się zmieniają. Jeśli pisalibyście wiersze bezpośrednio do tabeli, ich aktualizacja byłaby niemożliwa.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

Jeszcze jeden sposób, gdy nie wiesz, skąd wziąć identyfikatory dla swoich wierszy. Można po prostu haszować. Najprostszą wersją jest użycie 64-bitowego hasza.

Jedynym problemem jest to, że jeśli hasz jest 64-bitowy, to kolizje będą praktycznie pewne. Ponieważ jeśli mamy miliard wierszy, prawdopodobieństwo już staje się znaczące.

I nie byłoby dobrze tak haszować nazwy kampanii reklamowych. Jeśli kampanie reklamowe różnych firm się pomylą, to będzie coś niejasnego.

Jest prosty trik. Prawda, nie za bardzo nadaje się do poważnych danych, ale jeśli coś nie jest zbyt poważne, po prostu dodaj do klucza słownika jeszcze identyfikator klienta. Wtedy będą kolizje, ale tylko w obrębie jednego klienta. Taki sposób stosujemy do mapy linków w Yandex.Metrica. Mamy tam URL-e, przechowujemy hashe. Wiemy, że kolizje oczywiście się zdarzają. Jednak kiedy wyświetla się strona, prawdopodobieństwo, że na jednej stronie u jednego użytkownika jakieś URL-e się zlepiają i że to jeszcze zostanie zauważone, można zignorować.

Jako bonus – do wielu operacji wystarczą same hashe, a same ciągi można nigdzie nie przechowywać.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

Inny przykład, jeśli ciągi są krótkie, na przykład domeny stron. Można je przechowywać takimi, jakie są. Lub, na przykład, język przeglądarki ru – 2 bajty. Oczywiście, szkoda mi tych bajtów, ale nie martw się, 2 bajty to niewielka strata. Proszę, przechowuj je tak, jak są, nie przejmuj się.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

Inny przypadek, gdy jest bardzo dużo ciągów i przy tym wiele unikalnych, a także wiele potencjalnie nieograniczonych. Typowym przykładem są frazy wyszukiwania lub URL-e. Frazy wyszukiwania, w tym z powodu literówek. Sprawdźmy, ile unikalnych fraz wyszukiwania generuje się dziennie. Okazuje się, że są niemal połową wszystkich wydarzeń. W takim przypadku możesz pomyśleć, że trzeba znormalizować dane, obliczyć identyfikatory i złożyć do osobnej tabeli. Ale nie rób tego. Po prostu przechowuj te ciągi tak, jak są.

Lepiej – nie wymyślaj nic, bo jeśli będziesz przechowywać osobno, to będziesz musiał wykonać join. A ten join – w najlepszym razie to dostęp losowy do pamięci, jeśli uda się to w ogóle załadować do pamięci. Jeśli się nie zmieści, będą naprawdę poważne problemy.

A jeśli dane są przechowywane w in place, to po prostu odczytywane są w odpowiedniej kolejności z systemu plików i wszystko jest w porządku.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

Jeśli masz URL-e lub jakiekolwiek inne długie, skomplikowane ciągi, warto pomyśleć o tym, że można obliczyć jakąś wycinkę z góry i zapisać ją w osobnej kolumnie.

Na przykład można osobno przechowywać domenę dla URL-i. I jeśli naprawdę potrzebujesz domeny, po prostu użyj tej kolumny, a URL-e będą leżeć i nawet nie będziesz ich dotykać.

Zobaczmy, jaka jest różnica. W ClickHouse istnieje specjalizowana funkcja, która oblicza domenę. Jest bardzo szybka, zoptymalizowaliśmy ją. I szczerze mówiąc, nie spełnia ona standardu RFC, ale mimo to liczy wszystko, co potrzebujemy.

W jednym przypadku po prostu będziemy wyciągać URL-e i obliczać domenę. Zajmuje to 166 milisekund. A jeśli weźmiemy gotową domenę, to zajmie to zaledwie 67 milisekund, czyli prawie trzy razy szybciej. Co więcej, szybciej nie z powodu konieczności przeprowadzania obliczeń, lecz dlatego, że odczytujemy mniej danych.

Ciekawe, że w przypadku jednego zapytania, które jest wolniejsze, jest większa prędkość w gigabajtach na sekundę. Dzieje się tak, ponieważ odczytuje więcej gigabajtów. To zupełnie zbędne dane. Zapytanie działa szybciej, ale zajmuje więcej czasu.

A jeśli spojrzeć na objętość danych na dysku, to okazuje się, że URL ma 126 megabajtów, a domena zaledwie 5 megabajtów. To 25 razy mniej. Mimo to zapytanie wykonuje się tylko 4 razy szybciej. Ale to dlatego, że dane są gorące. Gdyby były zimne, byłoby na pewno 25 razy szybciej z powodu operacji wejścia-wyjścia na dysku.

Swoją drogą, jeśli ocenić, jak bardzo domena jest mniejsza od URL-a, to wynosi gdzieś około 4 razy. Ale jakoś na dysku dane zajmują 25 razy mniej. Dlaczego? Z powodu kompresji. I URL jest kompresowany, i domena jest kompresowana. Ale często URL zawiera mnóstwo śmieci.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

Oczywiście warto używać odpowiednich typów danych, które są specjalnie przeznaczone do wymaganych wartości lub które są odpowiednie. Jeśli korzystasz z IPv4, przechowuj UInt32*. Jeśli z IPv6, to FixedString(16), ponieważ adres IPv6 to 128 bitów, a więc przechowuj go w formacie binarnym.

A co zrobić, jeśli czasami masz adresy IPv4, a czasami IPv6? Tak, można przechowywać oba. Jedna kolumna dla IPv4, druga dla IPv6. Oczywiście jest opcja, aby IPv4 zamieniać na IPv6. To również zadziała, ale jeśli w zapytaniach często potrzebujesz konkretnie adresu IPv4, dobrze byłoby umieścić go w osobnej kolumnie.

* teraz w ClickHouse istnieją oddzielne typy danych dla IPv4, IPv6, które przechowują dane równie wydajnie, jak liczby, ale prezentują je w równie wygodny sposób, jak ciągi.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

Ważne jest również zauważyć, że warto dane wstępnie przetworzyć. Na przykład, jeśli do ciebie trafiają jakieś surowe logi. Może warto nie wrzucać ich od razu do ClickHouse, chociaż bardzo kusi, by nic nie robić i wszystko działało. Ale warto przeprowadzić te obliczenia, które można.

Na przykład wersja przeglądarki. W pewnym sąsiednim dziale, na który nie chcę wskazywać palcem, wersja przeglądarki jest przechowywana w ten sposób, tzn. jako ciąg znaków: 12.3. A następnie, aby wygenerować raport, dzielą ten ciąg na tablicę, a potem na pierwszy element tablicy. Oczywiście wszystko zwalnia. Pytałem, dlaczego tak robią. Odpowiedzieli mi, że nie lubią przedwczesnej optymalizacji. A ja nie lubię przedwczesnej pesymizacji.

Zatem w tym przypadku lepiej będzie podzielić dane na 4 kolumny. Nie bójcie się tego, ponieważ to ClickHouse. ClickHouse to baza danych kolumnowa. Im więcej starannie przygotowanych małych kolumn, tym lepiej. Będzie 5 BrowserVersion, róbcie 5 kolumn. To normalne.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

Teraz rozważmy, co zrobić, jeśli macie dużo bardzo długich ciągów, bardzo długich tablic. Nie należy ich w ogóle przechowywać w ClickHouse. Zamiast tego można w ClickHouse zapisać tylko jakiś identyfikator. A te długie ciągi wrzućcie do jakiegoś innego systemu.

Na przykład, w jednym z naszych serwisów analitycznych są pewne parametry zdarzeń. I jeśli dla zdarzeń przychodzi wiele parametrów, po prostu przechowujemy pierwsze 512, które się trafi. Bo 512 – nie jest szkoda.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

A jeśli nie jesteście pewni swoich typów danych, to możecie także zapisać dane w ClickHouse, ale w tabeli tymczasowej typu Log, specjalnej do danych tymczasowych. Następnie możecie przeanalizować, jakie macie tam rozkłady wartości, co w ogóle jest i ustalić poprawne typy.

* obecnie w ClickHouse jest typ danych LowCardinality który pozwala efektywnie przechowywać ciągi z mniejszymi kosztami obliczeniowymi.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

Teraz rozważmy jeszcze jeden interesujący przypadek. Czasami u ludzi wszystko działa jakoś dziwnie. Wchodzę i widzę coś takiego. Od razu wyobrażam sobie, że zrobił to jakiś bardzo doświadczony, mądry administrator, który ma duże doświadczenie w konfigurowaniu MySQL w wersji 3.23.

Tutaj widzimy tysiąc tabel, w każdej z nich zapisany jest reszta z dzielenia nie wiadomo czego przez tysiąc.

W zasadzie szanuję cudze doświadczenie, a także rozumiem, przez jakie cierpienia może być to doświadczenie zdobywane.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

I przyczyny są mniej więcej jasne. To stare stereotypy, które mogły się nagromadzić w pracy z innymi systemami. Na przykład w tabelach MyISAM nie ma klastrowanego klucza podstawowego. Taki sposób podziału danych może być rozpaczliwą próbą uzyskania tej samej funkcjonalności.

Inny powód to trudności związane z przeprowadzaniem operacji typu alter na dużych tabelach. Wszystko będzie zablokowane. Chociaż w nowoczesnych wersjach MySQL ten problem nie jest już tak poważny.

Albo na przykład mikroszardowanie, ale o tym trochę później.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

W ClickHouse nie trzeba tego robić, ponieważ, po pierwsze, klucz podstawowy jest klastrowany, a dane są uporządkowane według klucza podstawowego.

Czasami pytają mnie: "Jak zmienia się wydajność zapytań zakresowych w ClickHouse w zależności od rozmiaru tabeli?" Mówię, że w żaden sposób się nie zmienia. Na przykład, jeśli masz tabelę miliardów wierszy i odczytujesz zakres jednego miliona wierszy, wszystko jest w porządku. Jeśli w tabeli jest trylion wierszy i odczytujesz milion wierszy, to będzie niemal to samo.

Po drugie, nie potrzebujesz różnych rzeczy typu ręczne partycjonowanie. Jeśli wejdziesz i zajrzysz, co tam jest w systemie plików, zobaczysz, że tabela to dość poważna sprawa. I tam w środku jest coś w rodzaju partycji. To znaczy, że ClickHouse robi wszystko za Ciebie i nie musisz cierpieć.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

Alter w ClickHouse jest bezpłatny, jeśli chodzi o alter add/drop column.

I nie warto tworzyć małych tabel, ponieważ jeśli masz tabelę z 10 wierszami lub 10 000 wierszy, to jest całkowicie nieistotne. ClickHouse to system, który optymalizuje throughput, a nie latency, więc przetwarzanie 10 wierszy nie ma sensu.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

Prawidłowo jest używać jednej dużej tabeli. Pozbądź się starych stereotypów, wszystko będzie dobrze.

A jako bonus w naszej najnowszej wersji pojawiła się możliwość tworzenia dowolnego klucza partycjonowania, aby móc przeprowadzać różne operacje konserwacyjne na pojedynczych partycjach.

Na przykład, potrzebujesz wielu małych tabel, na przykład, gdy zachodzi potrzeba przetwarzania jakichś pośrednich danych, otrzymujesz fragmenty i musisz na nich przeprowadzać transformacje przed zapisaniem do tabeli docelowej. W tym przypadku jest wspaniały silnik tabeli – StripeLog. To jest coś jak TinyLog, tylko lepsze.

* teraz w ClickHouse jest także funkcja tabelaryczna input.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

Kolejnym antywzorem jest mikrodzielnie. Na przykład, musisz podzielić dane i masz 5 serwerów, a jutro będzie 6 serwerów. Zastanawiasz się, jak te dane przerebalansować. Zamiast tego dzielisz je nie na 5 shardów, a na 1 000 shardów. A następnie przypisujesz każdy z tych mikrodzielników do oddzielnego serwera. I okaże się, że na jednym serwerze będzie 200 ClickHouse, na przykład. Oddzielne instancje na oddzielnych portach lub oddzielne bazy danych.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

Ale w ClickHouse to nie jest zbyt dobre. Ponieważ nawet jeden instancja ClickHouse stara się wykorzystać wszystkie dostępne zasoby serwera do przetwarzania jednego zapytania. Tzn. masz jakiś serwer i na przykład 56 rdzeni procesora. Wykonujesz zapytanie, które trwa jedną sekundę i wykorzysta 56 rdzeni. A jeśli umieścisz tam 200 ClickHouse na jednym serwerze, to uruchomi się 10 000 wątków. W skrócie, wszystko będzie bardzo źle.

Innym powodem jest to, że rozkład pracy pomiędzy te instancje będzie nierównomierny. Niektóre zakończą wcześniej, inne później. Gdyby wszystko działo się w jednym instancji, to ClickHouse sam by sobie poradził z odpowiednim rozkładem danych pomiędzy wątki.

I jeszcze jednym powodem jest to, że będzie międzyprocesowa komunikacja przez TCP. Dane będą musiały być serializowane, deserializowane i to olbrzymia liczba mikrodzielników. Po prostu będzie to nieefektywne.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

Kolejnym antywzorem, choć trudno go nazwać antywzorem, jest duża liczba wstępnej agregacji.

Ogólnie rzecz biorąc, wstępna agregacja to coś dobrego. Miałeś miliard wierszy, zgrupowałeś je i stało się 1 000 wierszy, a teraz zapytanie wykonuje się natychmiast. Wszystko jest wspaniałe. Można tak robić. A w tym celu nawet w ClickHouse jest specjalny typ tabeli AggregatingMergeTree, który wykonuje inkrementalną agregację podczas wstawiania danych.

Są jednak sytuacje, gdy myślisz, że będziemy agregować dane w ten sposób i jeszcze tak. A w pewnym sąsiednim dziale, którego nazwiska nie chcę podawać, używają tabel SummingMergeTree do sumowania według klucza głównego, używając jako klucza głównego około 20 różnych kolumn. Dla ostrożności zmieniłem nazwy niektórych kolumn, ale wygląda to mniej więcej tak.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

I pojawiają się pewne problemy. Po pierwsze, objętość danych nie zmniejsza się zbytnio. Na przykład zmniejsza się trzykrotnie. Trzykrotne zmniejszenie to byłaby dobra cena, by pozwolić sobie na nieograniczone możliwości analityki, które pojawiają się, gdy dane nie są agregowane. Jeśli dane są agregowane, to zamiast analityki otrzymujesz jedynie marną statystykę.

Co szczególnie irytuje? To, że ludzie z sąsiedniego działu przychodzą i czasami proszą o dodanie jeszcze jednej kolumny do klucza głównego. Tzn. tak agregowaliśmy dane, a teraz chcemy trochę więcej. Ale w ClickHouse nie ma możliwości zmiany klucza głównego. Dlatego trzeba pisać jakieś skrypty w C++. A ja nie lubię skryptów, nawet jeśli są w C++.

Jeśli spojrzysz, do czego stworzono ClickHouse, to nieagregowane dane to dokładnie ten scenariusz, dla którego został stworzony. Jeśli używasz ClickHouse do nieagregowanych danych, to robisz wszystko dobrze. Jeśli agregujesz, to to czasami można wybaczyć.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

Jeszcze jeden interesujący przypadek – to zapytania w nieskończonej pętli. Czasem wchodzę na jakiś serwer produkcyjny i patrzę na show processlist. I za każdym razem odkrywam, że dzieje się coś strasznego.

Na przykład coś takiego. Od razu widać, że wszystko mogło być wykonane w jednym zapytaniu. Wystarczy wpisać tam url in i listę.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

Dlaczego tak wiele zapytań w nieskończonej pętli jest złe? Jeśli indeks nie jest używany, będzie wiele przejść przez te same dane. Ale jeśli indeks jest używany, na przykład masz klucz główny według ru i wpisujesz url = coś tam. I myślisz, że będzie czytane punktowo z tabeli jeden url, wszystko będzie w porządku. Ale w rzeczywistości nie. Ponieważ ClickHouse robi to wszystko w paczkach.

Kiedy potrzebuje odczytać jakiś zakres danych, odczytuje trochę więcej, ponieważ indeks w ClickHouse jest rozrzedzony. Ten indeks nie pozwala znaleźć w tabeli jednej pojedynczej linii, tylko jakiś zakres. Dane są kompresowane w blokach. Aby odczytać jedną linię, trzeba wziąć cały blok i go rozpakować. A jeśli wykonujesz wiele zapytań, będziesz miał wiele powtórzeń takich i mnóstwo pracy będzie wykonywane raz po raz.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

Jako bonus można zauważyć, że w ClickHouse nie warto się bać przesyłania nawet megabajtów, a nawet setek megabajtów do sekcji IN. Pamiętam z naszej praktyki, że jeśli w MySQL przesyłamy mnóstwo wartości do sekcji IN, na przykład przesyłamy tam 100 megabajtów jakichś liczb, to MySQL zużywa 10 gigabajtów pamięci i nic więcej się nie dzieje, wszystko działa słabo.

A drugą rzeczą jest to, że w ClickHouse, jeśli twoje zapytania wykorzystują indeks, to zawsze nie jest wolniejsze niż pełne skanowanie, tzn. jeśli trzeba odczytać prawie całą tabelę, będzie to robiło sekwencyjnie i odczyta całą tabelę. W ogólnym ujęciu samo się ogarnie.

Jednak pojawiają się pewne trudności. Na przykład to, że IN z podzapytaniem nie wykorzystuje indeksu. Ale to nasz problem i musimy to naprawić. Nic fundamentalnego tutaj nie ma. Będziemy to naprawiać.

I jeszcze jedna ciekawa rzecz – to, że jeśli masz bardzo długie zapytanie i rozproszoną obróbkę zapytań, to to bardzo długie zapytanie będzie wysyłane do każdego serwera bez kompresji. Na przykład, 100 megabajtów i 500 serwerów. I odpowiednio, przez sieć zostanie przesłane 50 gigabajtów. Zostanie przesłane, a potem wszystko zostanie pomyślnie wykonane.

* już używa; wszystko naprawione, jak obiecano.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

I dość częstym przypadkiem jest, gdy zapytania przychodzą z API. Na przykład, stworzyłeś jakiś swój serwis. I jeśli twój serwis jest komuś potrzebny, otworzyłeś API i dosłownie po dwóch dniach widzisz, że dzieje się coś dziwnego. Wszystko jest przeciążone i przychodzą jakieś okropne zapytania, które nigdy nie powinny były się pojawić.

I rozwiązanie jest jedno. Jeśli otworzyłeś API, to będziesz musiał wprowadzić ograniczenia. Na przykład, wprowadzić jakieś kwoty. Innych normalnych opcji nie ma. W przeciwnym razie od razu napiszą skrypt i będą problemy.

W ClickHouse istnieje specjalna funkcja - to jest liczenie kwot. Można przekazać własny klucz kwoty, na przykład wewnętrzny identyfikator użytkownika. Kwoty będą liczone niezależnie dla każdego z nich.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

Teraz jeszcze jedna interesująca rzecz. To replikacja na napędzie ręcznym.

Znam wiele przypadków, kiedy, mimo że ClickHouse ma wbudowaną obsługę replikacji, ludzie replikują ClickHouse ręcznie.

Jaki jest zasadniczy pomysł? Macie pipeline do przetwarzania danych, który działa niezależnie, na przykład w różnych centrach danych. Zapisujecie te same dane w ten sam sposób do ClickHouse. Prawda jest taka, że praktyka pokazuje, iż dane i tak będą się różnić z powodu jakichś specyficznych cech w waszym kodzie. Mam nadzieję, że w waszym przypadku tak nie będzie.

I od czasu do czasu i tak będziecie musieli zsynchronizować ręcznie. Na przykład raz w miesiącu administratorzy wykonują rsync.

W rzeczywistości znacznie łatwiej jest użyć wbudowanej replikacji ClickHouse. Ale mogą pojawić się pewne przeciwwskazania, ponieważ do tego trzeba korzystać z ZooKeeper. Nic złego nie powiem o ZooKeeper, generalnie system działa, ale bywa, że ludzie go nie używają z powodu fobii przed Java, ponieważ ClickHouse to bardzo dobra system napisana w C++, z którego można korzystać bez problemów. A ZooKeeper jest na Javie. I jakoś nie chce się nawet na to patrzeć, więc wtedy można użyć replikacji na napędzie ręcznym.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

ClickHouse to praktyczny system. Uwzględnia twoje potrzeby. Jeśli masz replikację na napędzie ręcznym, możesz stworzyć tabelę rozproszoną, która patrzy na twoje ręczne repliki i automatycznie wykonuje failover między nimi. Istnieje nawet specjalna opcja, która pozwala uniknąć fluktuacji, nawet jeśli twoje repliki systematycznie się różnią.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

Mogą wystąpić problemy, jeśli używasz prymitywnych silników tabel. ClickHouse to taka konstrukcja, która ma wiele różnych silników tabel. Do wszystkich poważnych przypadków, jak napisano w dokumentacji, używaj tabel z rodziny MergeTree. A wszystkie inne - to tak, do wyjątkowych przypadków lub do testów.

W tabeli MergeTree nie jest konieczne, aby mieć jakąś datę i czas. W każdym razie możesz z tego skorzystać. Jeśli nie ma daty i czasu, wpisz, że domyślnie to rok 2000. To będzie działać i nie będzie wymagać zasobów.

W nowej wersji serwera można nawet określić, że chcesz mieć niestandardowe partycjonowanie bez klucza partycji. To będzie to samo.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

Z drugiej strony, można używać prymitywnych silników tabel. Na przykład, załaduj dane raz i zobacz, pokręć i usuń je. Możesz używać Log.

Lub przechowywanie małych objętości do przetwarzania pośredniego – to StripeLog lub TinyLog.

Można używać pamięci, jeśli objętość danych jest mała i po prostu coś pokręć w pamięci operacyjnej.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

ClickHouse nie za bardzo lubi dane z nadmierną normalizacją.

Oto typowy przykład. To ogromna liczba URLi. Włożyłeś je do sąsiedniej tabeli. A potem zdecydowałeś się na JOIN, ale to nie zadziała, ponieważ ClickHouse obsługuje tylko Hash JOIN. Jeśli brakuje pamięci operacyjnej dla dużej ilości danych, które trzeba połączyć, to JOIN nie będzie możliwy.

Jeśli dane mają dużą kardynalność, to nie przejmuj się, przechowuj je w denormalizowanej formie, URL-e bezpośrednio w głównej tabeli.

* A teraz w ClickHouse jest również merge join, który działa w sytuacjach, gdy dane pośrednie nie mieszczą się w pamięci operacyjnej. Jednak jest to nieefektywne i zalecenie pozostaje w mocy.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

Jeszcze kilka przykładów, ale już mam wątpliwości, czy są one antywzorcowe.

ClickHouse ma jeden znany minus. Nie obsługuje aktualizacji. W pewnym sensie to nawet dobrze. Jeśli masz jakieś ważne dane, na przykład księgowość, nikt ich nie wyśle, ponieważ nie ma aktualizacji.

* Od dłuższego czasu dodano obsługę aktualizacji i usuwania w trybie wsadowym.

Są jednak pewne specjalne sposoby, które pozwalają na aktualizacje jakby w tle. Na przykład, tabele typu ReplaceMergeTree. Dokonują aktualizacji podczas tła łączącego. Możesz to wymusić za pomocą optymalizacji tabeli. Ale nie rób tego za często, ponieważ będzie to pełne przepisanie partycji.

Rozproszone JOIN w ClickHouse również są źle obsługiwane przez planner zapytań.

Źle, ale czasem w porządku.

Używanie ClickHouse tylko po to, aby odczytać dane z powrotem za pomocą select.

Nie polecałbym używania ClickHouse do rozbudowanych obliczeń. Ale to nie do końca prawda, ponieważ już odchodzimy od tej rekomendacji. Ostatnio dodaliśmy możliwość stosowania modeli uczenia maszynowego w ClickHouse – Catboost. To mnie martwi, bo myślę sobie: „Jaki straszny widok. Ileż to cykli na bajt!”. Bardzo mi żal wydawać cykle na bajty.

Efektywne wykorzystanie ClickHouse. Aleksiej Miłowidow (Yandex)

Ale nie bójcie się, instalujcie ClickHouse, wszystko będzie dobrze. W razie czego, mamy społeczność. A tak przy okazji, społeczność to wy. I jeśli macie jakieś problemy, możecie przynajmniej zajrzeć na nasz czat, i mam nadzieję, że wam pomogą.

Pytania

Dziękuję za prezentację! Gdzie mogę zgłosić awarię ClickHouse?

Możecie zgłaszać to do mnie osobiście już teraz.

Niedawno zacząłem używać ClickHouse. Od razu padł interfejs cli.

Miałeś szczęście.

Chwilę później również zniszczyłem serwer małym selectem.

Masz talent.

Zgłosiłem błąd na GitHubie, ale go zignorowano.

Zobaczymy.

Aleksiej oszukał mnie, żeby zaciągnąć na prezentację, obiecując opowiedzieć, jak kompresujecie dane wewnętrznie.

Bardzo prosto.

To zrozumiałem już wczoraj. Potrzebuję więcej konkretów.

Nie ma tam żadnych strasznych sztuczek. To po prostu kompresja po blokach. Domyślnie używa się LZ4, ale można włączyć ZSTD*. Bloki mają od 64 kilobajtów do 1 megabajta.

* istnieje również wsparcie dla wyspecjalizowanych kodeków kompresji, które można używać w łańcuchu z innymi algorytmami.

W blokach są po prostu surowe dane?

Nie do końca surowe. Są tam tablice. Jeśli macie kolumnę liczbową, to liczby są ułożone kolejno w tablicy.

Rozumiem.

Aleksiej, przykład, który miałeś z uniqExact nad adresami IP, to znaczy, że uniqExact jest wolniejszy dla ciągów niż dla liczb itd. A co jeśli zastosujemy sztuczkę i przekonwertujemy w momencie odczytu? To znaczy, wydaje mi się, że mówiliście, że na dysku to nie różni się zbytnio. Jeśli będziemy czytać z dysku ciągi, konwertować, to wtedy nasze agregaty będą szybsze, czy nie? A może jednak nieznacznie zyskamy? Wydaje mi się, że testowaliście to, ale jakoś nie zaznaczyliście w benchmarkach.

Myślę, że będzie to wolniejsze niż bez kasty. W takim przypadku trzeba sparsować adres IP z ciągu. Oczywiście, w ClickHouse również mamy zoptymalizowane parsowanie adresów IP. Bardzo się staraliśmy, ale macie tam liczby zapisane w formie dziesięciotysięcznej. Bardzo niewygodne. Z drugiej strony funkcja uniqExact będzie działać na ciągach wolniej nie tylko dlatego, że to ciągi, ale także dlatego, że wybierana jest inna specjalizacja algorytmu. Ciągi po prostu są przetwarzane inaczej.

A co, jeśli weźmiemy bardziej prymitywny typ danych? Na przykład, zapisaliśmy user id, który mamy w, zapisaliśmy go jako ciąg, a potem go skastowaliśmy, czy będzie to lepsze, czy nie?

Wątpię. Myślę, że będzie nawet gorzej, ponieważ parsowanie liczb to poważny problem. Wydaje mi się, że ten kolega miał nawet prezentację na temat trudności w parsowaniu liczb w formie dziesięciotysicznej, a może i nie.

Alieksei, bardzo dziękuję za prezentację! I jeszcze raz dziękuję za ClickHouse! Mam pytanie dotyczące planów. Czy jest planowana funkcja aktualizacji słowników nie w całości?

Tzn. częściowe przeładowanie?

Tak-tak. Typu możliwość ustawienia tam pola MySQL, tzn. aktualizować po, aby ładować tylko te dane, jeśli słownik jest bardzo duży.

Bardzo interesująca funkcja. Wydaje mi się, że jakaś osoba proponowała ją na naszym czacie. Może to nawet byłeś ty.

Nie sądzę, żebym to był ja.

Świetnie, teraz wychodzi, że są dwa zapytania. I można powoli zaczynać to robić. Ale od razu chcę was ostrzec, że ta funkcja jest dość prosta do zaimplementowania. Tzn. w zasadzie trzeba po prostu zapisać w tabeli numer wersji i pisać: wersja jest mniejsza niż taka. A to oznacza, że najprawdopodobniej zaproponujemy to zrobić entuzjastom. Czy jesteś entuzjastą?

Tak, ale niestety nie w C++.

Czy wasi koledzy potrafią pisać w C++?

Zaraz kogoś znajdę.

Świetnie*.

* możliwość została dodana dwa miesiące po prezentacji – została opracowana przez autora pytania i przesłana pull request.

Dziękuję!

Cześć! Dziękuję za prezentację! Wspominałeś, że ClickHouse bardzo dobrze wykorzystuje wszystkie dostępne mu zasoby. A prelegent obok z Luxoft mówił o swoim rozwiązaniu dla Poczty Rosyjskiej. Powiedział, że bardzo im się spodobał ClickHouse, ale nie użyli go zamiast swojego głównego konkurenta, właśnie dlatego, że zużywał cały procesor. I nie mogli go włączyć w swoją architekturę, w swojego ZooKeepera z dockerami. Czy jest możliwość jakoś ograniczyć ClickHouse, aby nie zużywał wszystkiego, co mu się udostępnia?

Tak, można to zrobić i jest to bardzo proste. Jeśli chcesz, aby używał mniej rdzeni, napisz po prostu set max_threads = 1. I wszystko, będzie wykonywał zapytania na jednym rdzeniu. Można zresztą różnym użytkownikom ustawić różne te parametry. Więc nie ma problemu. A kolegom z Luxoft przekaż, że nie dobrze, że nie znaleźli tej opcji w dokumentacji.

Aleksiej, cześć! Chciałem zadać takie pytanie. Już nie po raz pierwszy słyszę, że wielu zaczyna używać ClickHouse jako magazyn na logi. Na prezentacji mówiłeś, żeby tego nie robić, tzn. nie należy przechowywać długich linii. Jak się do tego odnosisz?

Po pierwsze, logi to z reguły nie są długie linie. Oczywiście bywają wyjątki. Na przykład, jakiś serwis pisany w javie, zgłasza wyjątek, który jest logowany. I tak w nieskończonej pętli, i kończy się miejsce na dysku twardym. Rozwiązanie jest bardzo proste. Jeśli linie są bardzo długie, to je tnij. A co to znaczy długie? Dziesiątki kilobajtów – to źle.

*w nowszych wersjach ClickHouse włączono "adaptacyjne granulowanie indeksów", co w dużej mierze rozwiązuje problem przechowywania długich linii.

A kilobajt – to w porządku?

W porządku.

Cześć! Dziękuję za prezentację! Już o to pytałem na czacie, ale nie pamiętam, czy otrzymałem odpowiedź. Czy planuje się jakoś rozszerzyć sekcję WITH na wzór CTE?

Na razie nie. Sekcja WITH to dla nas coś niezbyt poważnego. To dla nas taka mała funkcja.

Rozumiem. Dziękuję!

Dziękuję za prezentację! Bardzo interesująco! Mam globalne pytanie. Czy planujecie może wprowadzenie jakichś mechanizmów do usuwania danych?

Oczywiście. To nasze pierwsze zadanie w kolejce. Aktualnie intensywnie myślimy, jak wszystko zrobić poprawnie. I czas zacząć stukać w klawiaturę.

* naciskaliśmy przyciski na klawiaturze i wszystko zrobiliśmy.

Czy to wpłynie jakoś na wydajność systemu? Czy wstawianie będzie tak samo szybkie, jak teraz?

Możliwe, że same usunięcia i aktualizacje będą bardzo ciężkie, ale nie wpłynie to na wydajność zapytań selektywnych i wstawianie.

I jeszcze jedno małe pytanie. Na prezentacji mówiłeś o kluczu głównym. Mamy zatem partycjonowanie, które jest domyślnie miesięczne, prawda? Kiedy określamy zakres dat, który mieści się w miesiącu, to odczytywana jest tylko ta partycja, prawda?

Tak.

Takie pytanie. Jeśli nie możemy wydzielić żadnego klucza głównego, to czy słusznie byłoby zrobić go na podstawie pola „Data”, aby w tle była mniejsza reorganizacja tych danych, by były uporządkowane? Jeżeli nie masz zapytań zakresowych i nie możesz wybrać żadnego klucza głównego, czy warto umieścić datę w kluczu głównym?

Tak.

Może warto umieścić w kluczu głównym takie pole, po którym dane będą lepiej się kompresować, jeśli będą posortowane według tego pola. Na przykład, identyfikator użytkownika. Użytkownik, na przykład, odwiedza tę samą stronę. W tym przypadku umieszczasz ID użytkownika i czas. Wtedy dane będą lepiej się kompresować. Jeżeli chodzi o datę, jeśli naprawdę nie masz i nigdy nie masz zapytań zakresowych po datach, to możesz nie umieszczać daty w kluczu głównym.

Dziękuję bardzo!

Źródło: habr.com

Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS 🔥 Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS | ProHoster