{"id":91438,"date":"2020-08-13T19:42:36","date_gmt":"2020-08-13T17:42:36","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/effektivnoe-ispolzovanie-clickhouse-aleksej-milovidov-yandeks"},"modified":"2020-08-13T19:42:36","modified_gmt":"2020-08-13T17:42:36","slug":"effektivnoe-ispolzovanie-clickhouse-aleksej-milovidov-yandeks","status":"publish","type":"post","link":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/effektivnoe-ispolzovanie-clickhouse-aleksej-milovidov-yandeks","title":{"rendered":"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/8e42c1fffffcc964eacef240ea90bbc5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Poniewa\u017c ClickHouse jest wyspecjalizowanym systemem, wa\u017cne jest, aby przy jego u\u017cyciu uwzgl\u0119dni\u0107 cechy jego architektury. W tej prezentacji Aleksiej opowie o typowych b\u0142\u0119dach podczas korzystania z ClickHouse, kt\u00f3re mog\u0105 prowadzi\u0107 do niew\u0142a\u015bciwej pracy. Na przyk\u0142adach praktycznych poka\u017ce, jak wyb\u00f3r konkretnego schematu przetwarzania danych mo\u017ce znacz\u0105co wp\u0142yn\u0105\u0107 na wydajno\u015b\u0107.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>Cze\u015b\u0107 wszystkim! Nazywam si\u0119 Aleksiej, zajmuj\u0119 si\u0119 ClickHouse.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/7f5fc01663be58d3d25e518a4169b8cf.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Po pierwsze, od razu chcia\u0142bym Was uspokoi\u0107, \u017ce dzisiaj nie b\u0119d\u0119 m\u00f3wi\u0142, czym jest ClickHouse. Szczerze m\u00f3wi\u0105c, ju\u017c mi si\u0119 to znudzi\u0142o. Za ka\u017cdym razem to powtarzam. I pewnie wszyscy ju\u017c to wiedz\u0105. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/fae6bd07d098200643d591b8e5bf51e8.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Zamiast tego opowiem, jakie s\u0105 mo\u017cliwe pu\u0142apki, czyli jak mo\u017cna niew\u0142a\u015bciwie wykorzysta\u0107 ClickHouse. Tak naprawd\u0119 nie ma si\u0119 czego ba\u0107, poniewa\u017c rozwijamy ClickHouse jako system, kt\u00f3ry jest prosty, wygodny i dzia\u0142a od razu po zainstalowaniu. Wystarczy zainstalowa\u0107 i wszystko, \u017cadnych problem\u00f3w. <\/p>\n<p><\/p>\n<p>Jednak warto mie\u0107 na uwadze, \u017ce jest to system wyspecjalizowany i \u0142atwo mo\u017cna natkn\u0105\u0107 si\u0119 na nietypowy scenariusz u\u017cycia, kt\u00f3ry wyprowadzi ten system z jego strefy komfortu.<\/p>\n<p><\/p>\n<p>A wi\u0119c, jakie pu\u0142apki s\u0105 dost\u0119pne? G\u0142\u00f3wnie b\u0119d\u0119 m\u00f3wi\u0142 o oczywistych rzeczach. Wszystkim wszystko wydaje si\u0119 oczywiste, wszyscy rozumiej\u0105 i mog\u0105 cieszy\u0107 si\u0119, \u017ce s\u0105 tacy m\u0105drzy, a ci, kt\u00f3rzy nie rozumiej\u0105, dowiedz\u0105 si\u0119 czego\u015b nowego. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/bffacf353ff31b361460178e911f0e16.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Pierwszy najprostszy przyk\u0142ad, kt\u00f3ry niestety cz\u0119sto si\u0119 zdarza, to du\u017ca liczba insercji z ma\u0142ymi paczkami, czyli du\u017c\u0105 ilo\u015bci\u0105 ma\u0142ych insercji.<\/p>\n<p><\/p>\n<p>Je\u015bli spojrze\u0107, jak ClickHouse wykonuje insercj\u0119, to w jednym zapytaniu mo\u017cna wys\u0142a\u0107 nawet strumie\u0144 danych o rozmiarze terabajta. To nie stanowi problemu. <\/p>\n<p><\/p>\n<p>Zobaczmy, jaka b\u0119dzie typowa wydajno\u015b\u0107. Na przyk\u0142ad mamy tabel\u0119 z danymi Yandex.Metriki. Hit\u00f3w. 105 kolumn. 700 bajt\u00f3w w postaci nieskompresowanej. B\u0119dziemy wstawia\u0107, jak nale\u017cy, paczkami po milion wierszy. <\/p>\n<p><\/p>\n<p>Wstawiamy do tabeli MergeTree, otrzymujemy p\u00f3\u0142 miliona wierszy na sekund\u0119. \u015awietnie. W tabeli replikowanej b\u0119dzie to troch\u0119 mniej, oko\u0142o 400 000 wierszy na sekund\u0119. <\/p>\n<p><\/p>\n<p>A je\u015bli w\u0142\u0105czymy kworumow\u0105 insercj\u0119, to wynosi to nieco mniej, ale nadal przyzwoita wydajno\u015b\u0107, 250 000 wierszy na sekund\u0119. Kworumowa insercja to niedokumentowana mo\u017cliwo\u015b\u0107 w ClickHouse*.<\/p>\n<p><\/p>\n<p>* stan na 2020 rok, <noindex><a rel=\"nofollow\" href=\"https:\/\/clickhouse.tech\/docs\/en\/operations\/settings\/settings\/#settings-insert_quorum\">ju\u017c udokumentowana<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/668498fc82a0f6e851d05e6e1ea67033.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Co si\u0119 stanie, je\u015bli wszystko b\u0119dzie robione \u017ale? Wstawiamy jedno pole na raz do tabeli MergeTree i uzyskujemy 59 wierszy na sekund\u0119. To jest 10 000 razy wolniej. W ReplicatedMergeTree \u2013 6 wierszy na sekund\u0119. A je\u015bli dodatkowo w\u0142\u0105czy si\u0119 quorum, to wychodzi 2 wiersze na sekund\u0119. Moim zdaniem to jaki\u015b totalny s\u0105d. Jak mo\u017cna tak zwalnia\u0107? Nawet na moim T-shircie jest napisane, \u017ce ClickHouse nie powinien zwalnia\u0107. A jednak czasami si\u0119 zdarza. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/4c771eddc4e8453f60ef91123ae5d109.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>W rzeczywisto\u015bci to nasza wada. Mogliby\u015bmy to zrobi\u0107 tak, aby wszystko dzia\u0142a\u0142o poprawnie, ale tego nie zrobili\u015bmy. A nie zrobili\u015bmy tego, poniewa\u017c w naszym scenariuszu to nie by\u0142o wymagane. Mieli\u015bmy ju\u017c wsady. Po prostu przychodzi\u0142y do nas wsady i wszystko dzia\u0142a\u0142o bez problem\u00f3w. Wstawiamy i wszystko dzia\u0142a normalnie. Ale oczywi\u015bcie mog\u0105 wyst\u0105pi\u0107 r\u00f3\u017cne scenariusze. Na przyk\u0142ad, gdy masz wiele serwer\u00f3w, na kt\u00f3rych generowane s\u0105 dane. I wstawiaj\u0105 dane niezbyt cz\u0119sto, ale nadal wyst\u0119puj\u0105 cz\u0119ste wstawienia. I jako\u015b trzeba tego unikn\u0105\u0107. <\/p>\n<p><\/p>\n<p>Z technicznego punktu widzenia chodzi o to, \u017ce gdy wykonujesz insert w ClickHouse, dane nie trafiaj\u0105 do \u017cadnego memtable. Nawet nie mamy prawdziwego log structure MergeTree, tylko po prostu MergeTree, poniewa\u017c nie ma ani loga, ani memTable. Po prostu od razu zapisujemy dane w systemie plik\u00f3w, ju\u017c roz\u0142o\u017cone na kolumny. I je\u015bli masz 100 kolumn, to musisz zapisa\u0107 wi\u0119cej ni\u017c 200 plik\u00f3w w osobnym katalogu. To wszystko jest do\u015b\u0107 uci\u0105\u017cliwe. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/24688fe3d39d81b92f12ac1b8b21425b.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Pojawia si\u0119 pytanie: \u201eJak to zrobi\u0107 prawid\u0142owo?\u201d, je\u015bli sytuacja jest taka, \u017ce musisz w jaki\u015b spos\u00f3b zapisywa\u0107 dane w ClickHouse.<\/p>\n<p><\/p>\n<p>Spos\u00f3b 1. To najprostszy spos\u00f3b. U\u017cyj jakiej\u015b rozproszonej kolejki. Na przyk\u0142ad, Kafka. Po prostu wyci\u0105gasz dane z Kafka, batchujesz co sekund\u0119. I wszystko b\u0119dzie w porz\u0105dku, zapisujesz i wszystko dzia\u0142a normalnie. <\/p>\n<p><\/p>\n<p>Wady s\u0105 takie, \u017ce Kafka to kolejny skomplikowany system rozproszony. Rozumiem, je\u015bli w twojej firmie ju\u017c jest Kafka. To dobrze, to wygodne. Ale je\u015bli jej nie ma, to warto trzy razy si\u0119 zastanowi\u0107, zanim wci\u0105gniesz kolejny system rozproszony do swojego projektu. Dlatego warto rozwa\u017cy\u0107 alternatywy. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/4f687221e8c7443abf02fb002c4eba5b.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Metoda 2. Oto taka oldschoolowa alternatywa, kt\u00f3ra jest bardzo prosta. Macie jaki\u015b serwer, kt\u00f3ry generuje wasze logi. I on po prostu zapisuje wasze logi do pliku. Co sekund\u0119, na przyk\u0142ad, zmieniamy nazw\u0119 pliku, tworzymy nowy. A oddzielny skrypt, albo wed\u0142ug crona, albo jaki\u015b daemon pobiera najstarszy plik i zapisuje do ClickHouse. Je\u015bli zapisujecie logi co sekund\u0119, to wszystko b\u0119dzie dzia\u0142a\u0107 doskonale. <\/p>\n<p><\/p>\n<p>Jednak wad\u0105 tego rozwi\u0105zania jest to, \u017ce je\u015bli wasz serwer, na kt\u00f3rym generowane s\u0105 logi, gdzie\u015b zniknie, to tak\u017ce dane znikn\u0105.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/b4c28b6df87386c42b6908bdfccb6b90.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Metoda 3. Jest jeszcze jeden ciekawy spos\u00f3b, kt\u00f3ry nie wymaga plik\u00f3w tymczasowych. Na przyk\u0142ad, macie jak\u0105\u015b reklamow\u0105 p\u0119tl\u0119 lub inny interesuj\u0105cy daemon, kt\u00f3ry generuje dane. Mo\u017cecie gromadzi\u0107 paczk\u0119 danych bezpo\u015brednio w pami\u0119ci operacyjnej, w buforze. I gdy up\u0142ynie wystarczaj\u0105ca ilo\u015b\u0107 czasu, odk\u0142adacie ten bufor na bok, tworzycie nowy, a w oddzielnym w\u0105tku to, co ju\u017c si\u0119 zgromadzi\u0142o, wstawiajcie do ClickHouse.<\/p>\n<p><\/p>\n<p>Z drugiej strony dane r\u00f3wnie\u017c znikaj\u0105 przy kill -9. Je\u015bli wasz serwer si\u0119 zawiesi, to te dane stracicie. I jeszcze problem polega na tym, \u017ce je\u015bli nie mogliby\u015bcie zapisa\u0107 do bazy, to dane gromadz\u0105 si\u0119 w pami\u0119ci operacyjnej. I albo sko\u0144czy si\u0119 pami\u0119\u0107 operacyjna, albo po prostu stracicie dane. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/dc375b22fcb26cfa111d0bdb4563aa88.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Metoda 4. Jeszcze jeden ciekawy spos\u00f3b. Macie jaki\u015b proces serwerowy. I mo\u017ce on wysy\u0142a\u0107 dane do ClickHouse od razu, ale robi to w jednym po\u0142\u0105czeniu. Na przyk\u0142ad, wysy\u0142a http-zapytanie z transfer-encoding: chunked z insert'em. I generuje kawa\u0142ki ju\u017c niezbyt rzadko, mo\u017cna wysy\u0142a\u0107 ka\u017cd\u0105 linijk\u0119, chocia\u017c b\u0119dzie overhead na ramki tych danych. <\/p>\n<p><\/p>\n<p>Jednak w ka\u017cdym razie dane b\u0119d\u0105 wysy\u0142ane do ClickHouse od razu. A ClickHouse sam je zbuforuje. <\/p>\n<p><\/p>\n<p>Ale r\u00f3wnie\u017c pojawiaj\u0105 si\u0119 problemy. Teraz stracicie dane, w tym przypadku, gdy wasz proces zako\u0144czy dzia\u0142anie, a je\u015bli proces ClickHouse si\u0119 zawiesi, poniewa\u017c to b\u0119dzie nieuko\u0144czony insert. A w ClickHouse inserts s\u0105 atomowe do pewnego okre\u015blonego progu w liczbie wierszy. W zasadzie to ciekawy spos\u00f3b. Mo\u017cna go r\u00f3wnie\u017c u\u017cywa\u0107.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/6a18a974b9600ade377a870390e95d3d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Metoda 5. Oto kolejny interesuj\u0105cy spos\u00f3b. To serwer do batchowania danych stworzony przez spo\u0142eczno\u015b\u0107. Sam go nie sprawdza\u0142em, wi\u0119c niczego nie mog\u0119 zagwarantowa\u0107. Zreszt\u0105, dla samego ClickHouse r\u00f3wnie\u017c nie ma \u017cadnych gwarancji. To te\u017c open source, ale z drugiej strony mogli\u015bcie przyzwyczai\u0107 si\u0119 do pewnego standardu jako\u015bci, kt\u00f3ry staramy si\u0119 zapewnia\u0107. Co do tego rozwi\u0105zania \u2013 nie wiem, zajrzyjcie na GitHub, sprawd\u017acie kod. Mo\u017ce napisano co\u015b sensownego. <\/p>\n<p><\/p>\n<p>* wed\u0142ug stanu na 2020 rok, nale\u017cy r\u00f3wnie\u017c uwzgl\u0119dni\u0107 w rozwa\u017caniach <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/en\/company\/vk\/blog\/430168\/\">KittenHouse<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/ae6a04af63ae4e7fa160c002fdb6d506.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Metoda 6. Innym sposobem jest wykorzystanie tabel buforowych. Zalet\u0105 tego rozwi\u0105zania jest to, \u017ce bardzo \u0142atwo mo\u017cna zacz\u0105\u0107 z niego korzysta\u0107. Tworzysz tabel\u0119 buforow\u0105 i wstawiasz do niej dane. <\/p>\n<p><\/p>\n<p>A wad\u0105 jest to, \u017ce problem nie jest rozwi\u0105zywany w ca\u0142o\u015bci. Je\u015bli przy wstawianiu typu MergeTree musisz grupowa\u0107 dane po jednym batchu na sekund\u0119, to przy wstawianiu do tabeli buforowej musisz grupowa\u0107 co najmniej do kilku tysi\u0119cy na sekund\u0119. Je\u015bli b\u0119dzie wi\u0119cej ni\u017c 10 000 na sekund\u0119, to i tak b\u0119dzie \u017ale. Natomiast je\u015bli wstawiasz w partiach, to widzieli\u015bcie, \u017ce mo\u017cna osi\u0105gn\u0105\u0107 setki tysi\u0119cy wierszy na sekund\u0119. A to ju\u017c na dosy\u0107 ci\u0119\u017ckich danych. <\/p>\n<p><\/p>\n<p>I r\u00f3wnie\u017c tabele buforowe nie maj\u0105 loga. Je\u015bli z twoim serwerem co\u015b jest nie tak, dane zostan\u0105 utracone. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/9bb16bf5e8145cc8368b11e54c86c837.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>A jako bonus, niedawno w ClickHouse pojawi\u0142a si\u0119 mo\u017cliwo\u015b\u0107 pobierania danych z Kafka. Istnieje silnik tabel \u2013 Kafka. Po prostu go tworzysz. I mo\u017cna na niego na\u0142o\u017cy\u0107 materializowane widoki. W takim przypadku sam b\u0119dzie wyci\u0105ga\u0142 dane z Kafka i wstawia\u0142 je do odpowiednich tabel. <\/p>\n<p><\/p>\n<p>I szczeg\u00f3lnie cieszy w tej funkcjonalno\u015bci to, \u017ce nie my j\u0105 stworzyli\u015bmy. To funkcja spo\u0142eczno\u015bci. I kiedy m\u00f3wi\u0119 'funkcja spo\u0142eczno\u015bci', m\u00f3wi\u0119 to bez \u017cadnego pogardzenia. Kod czytali\u015bmy, robili\u015bmy przegl\u0105dy, powinno dzia\u0142a\u0107 poprawnie. <\/p>\n<p><\/p>\n<p>* wed\u0142ug stanu na 2020 rok, pojawi\u0142o si\u0119 podobne wsparcie dla <noindex><a rel=\"nofollow\" href=\"https:\/\/clickhouse.tech\/docs\/en\/engines\/table-engines\/integrations\/rabbitmq\/\">RabbitMQ<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/15dc61dfd435f5f8640395b7de480fe2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Co jeszcze mo\u017ce by\u0107 niewygodne lub zaskakuj\u0105ce przy wstawianiu danych? Je\u015bli robisz zapytanie insert values i w values wpisujesz jakie\u015b wyra\u017cenia obliczeniowe. Na przyk\u0142ad, now() \u2013 to r\u00f3wnie\u017c jest wyra\u017cenie obliczeniowe. W takim przypadku ClickHouse musi uruchomi\u0107 interpreter tych wyra\u017ce\u0144 dla ka\u017cdego wiersza, co znacznie obni\u017ca wydajno\u015b\u0107. Lepiej tego unika\u0107.<\/p>\n<p><\/p>\n<p>* aktualnie problem jest ca\u0142kowicie rozwi\u0105zany, a regresji wydajno\u015bci przy u\u017cywaniu wyra\u017ce\u0144 w VALUES ju\u017c nie ma.<\/p>\n<p><\/p>\n<p>Inny przyk\u0142ad, kiedy mog\u0105 wyst\u0105pi\u0107 pewne problemy, to kiedy w jednym batchu dane dotycz\u0105 wielu partycji. Domy\u015blnie w ClickHouse partycje s\u0105 wed\u0142ug miesi\u0119cy. Je\u015bli wstawiasz batch z milionem wierszy, a dane si\u0119gaj\u0105 kilku lat, to pojawi si\u0119 kilka dziesi\u0105tek partycji. I to odpowiada temu, \u017ce b\u0119d\u0105 batchy o wielko\u015bci kilkadziesi\u0105t razy mniejszej, poniewa\u017c wewn\u0105trz zawsze s\u0105 najpierw dzielone wed\u0142ug partycji.<\/p>\n<p><\/p>\n<p>* niedawno w ClickHouse w trybie eksperymentalnym dodano wsparcie dla kompaktowego formatu blok\u00f3w oraz blok\u00f3w w pami\u0119ci operacyjnej z logowaniem do przodu, co prawie ca\u0142kowicie rozwi\u0105zuje problem.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/b8c6cecdba53559dad31ed11713a980d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Teraz przyjrzyjmy si\u0119 drugiemu rodzajowi problemu \u2013 typizacji danych. <\/p>\n<p><\/p>\n<p>Typizacja danych mo\u017ce by\u0107 \u015bcis\u0142a lub tekstowa. Tekstowa to wtedy, gdy po prostu zadeklarujesz, \u017ce wszystkie pola s\u0105 typu string. To jest niew\u0142a\u015bciwe. Nie nale\u017cy tego robi\u0107. <\/p>\n<p><\/p>\n<p>Zrozummy, jak to zrobi\u0107 poprawnie w przypadkach, kiedy chcemy powiedzie\u0107, \u017ce jakie\u015b pole to string, i niech ClickHouse si\u0119 tym zajmie, a ja si\u0119 nie b\u0119d\u0119 przejmowa\u0142. Mimo to warto podj\u0105\u0107 pewne wysi\u0142ki. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/a0fdcf6423933293318411242fe2ede7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Na przyk\u0142ad mamy adres IP. W jednym przypadku zachowali\u015bmy go jako string. Na przyk\u0142ad 192.168.1.1. A w innym przypadku b\u0119dzie to liczba typu UInt32*. 32 bity wystarcz\u0105 dla adresu IPv4.<\/p>\n<p><\/p>\n<p>Po pierwsze, jak nie jest dziwne, dane skompresuj\u0105 si\u0119 mniej wi\u0119cej tak samo. B\u0119dzie jaka\u015b r\u00f3\u017cnica, oczywi\u015bcie, ale nie tak du\u017ca. Wi\u0119c nie ma wi\u0119kszych problem\u00f3w z wej\u015bciem\/wyj\u015bciem dyskowym. <\/p>\n<p><\/p>\n<p>Ale jest znacz\u0105ca r\u00f3\u017cnica w czasie procesora i czasie wykonywania zapytania. <\/p>\n<p><\/p>\n<p>Obliczaj\u0105c liczb\u0119 unikalnych adres\u00f3w IP, je\u015bli s\u0105 one przechowywane jako liczby, otrzymujemy 137 milion\u00f3w wierszy na sekund\u0119. Je\u015bli to samo w postaci string\u00f3w, to 37 milion\u00f3w wierszy na sekund\u0119. Nie wiem, dlaczego tak si\u0119 sta\u0142o. Sam wykonywa\u0142em te zapytania. Mimo to jest to oko\u0142o 4 razy wolniej. <\/p>\n<p><\/p>\n<p>A je\u015bli policzy\u0107 r\u00f3\u017cnic\u0119 w miejscu na dysku, to r\u00f3wnie\u017c jest r\u00f3\u017cnica. I r\u00f3\u017cnica wynosi oko\u0142o \u0107wierci, poniewa\u017c unikalnych adres\u00f3w IP jest wystarczaj\u0105co du\u017co. I gdyby tutaj by\u0142y wiersze z ma\u0142\u0105 ilo\u015bci\u0105 r\u00f3\u017cnych warto\u015bci, to spokojnie skompresowa\u0142yby si\u0119 w s\u0142ownik do mniej wi\u0119cej tej samej obj\u0119to\u015bci. <\/p>\n<p><\/p>\n<p>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.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/f74dbfdab5a9e26fa044a5870a8cc00d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Let\u2019s consider different scenarios. <\/p>\n<p><\/p>\n<p>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. <\/p>\n<p><\/p>\n<p>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\u2019s fine, but when it includes 'MO', it feels quite disheartening. That's quite a few bytes. <\/p>\n<p><\/p>\n<p>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. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/cc6e871136dab8f8a35246a5af512cda.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>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. <\/p>\n<p><\/p>\n<p>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.<\/p>\n<p><\/p>\n<p>* In recent versions of ClickHouse, ALTER is fully non-blocking.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/d7284fa5be583ab063bb6de0b60f54d4.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>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. <\/p>\n<p><\/p>\n<p>To jest wyspecjalizowany, ale bardzo efektywny spos\u00f3b na wykonanie po\u0142\u0105czenia z zewn\u0119trzn\u0105 tabel\u0105. Istniej\u0105 dwa warianty. W jednym z nich dane b\u0119d\u0105 w pe\u0142ni zbuforowane, ca\u0142kowicie obecne w pami\u0119ci operacyjnej i aktualizowane z pewn\u0105 okresowo\u015bci\u0105. W drugim wariancie, je\u015bli dane nie mieszcz\u0105 si\u0119 w pami\u0119ci, mo\u017cna je cz\u0119\u015bciowo zbuforowa\u0107. <\/p>\n<p><\/p>\n<p>Oto przyk\u0142ad. Jest Yandex.Direct. I tam jest kampania reklamowa oraz banery. Kampanii reklamowych jest prawdopodobnie kilkana\u015bcie milion\u00f3w. W du\u017cej mierze mieszcz\u0105 si\u0119 one w pami\u0119ci operacyjnej. A baner\u00f3w \u2013 s\u0105 miliardy, one si\u0119 nie mieszcz\u0105. Dlatego korzystamy z buforowanego s\u0142ownika z MySQL.<\/p>\n<p><\/p>\n<p>Jedynym problemem jest to, \u017ce buforowany s\u0142ownik b\u0119dzie dzia\u0142a\u0142 poprawnie, je\u015bli wsp\u00f3\u0142czynnik trafie\u0144 wynosi blisko 100%. Je\u015bli jest mniejszy, to przy przetwarzaniu zapyta\u0144 na ka\u017cd\u0105 parti\u0119 danych trzeba b\u0119dzie rzeczywi\u015bcie pobra\u0107 brakuj\u0105ce klucze i zaci\u0105ga\u0107 dane z MySQL. W przypadku ClickHouse mog\u0119 si\u0119 jeszcze upewni\u0107, \u017ce tak, nie spowalnia, natomiast o innych systemach nie b\u0119d\u0119 m\u00f3wi\u0107.<\/p>\n<p><\/p>\n<p>A jako bonus, s\u0142owniki to bardzo prosty spos\u00f3b na aktualizacj\u0119 danych w ClickHouse z dat\u0105 wsteczn\u0105. To znaczy, \u017ce je\u015bli mieli\u015bcie raport dotycz\u0105cy kampanii reklamowych, a u\u017cytkownik po prostu zmieni\u0142 kampani\u0119 reklamow\u0105, to we wszystkich starych danych, we wszystkich raportach te dane te\u017c si\u0119 zmieniaj\u0105. Je\u015bli pisaliby\u015bcie wiersze bezpo\u015brednio do tabeli, ich aktualizacja by\u0142aby niemo\u017cliwa. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/a5a2919d6be7d00c0ad5875b9a8f0f31.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Jeszcze jeden spos\u00f3b, gdy nie wiesz, sk\u0105d wzi\u0105\u0107 identyfikatory dla swoich wierszy. Mo\u017cna po prostu haszowa\u0107. Najprostsz\u0105 wersj\u0105 jest u\u017cycie 64-bitowego hasza. <\/p>\n<p><\/p>\n<p>Jedynym problemem jest to, \u017ce je\u015bli hasz jest 64-bitowy, to kolizje b\u0119d\u0105 praktycznie pewne. Poniewa\u017c je\u015bli mamy miliard wierszy, prawdopodobie\u0144stwo ju\u017c staje si\u0119 znacz\u0105ce. <\/p>\n<p><\/p>\n<p>I nie by\u0142oby dobrze tak haszowa\u0107 nazwy kampanii reklamowych. Je\u015bli kampanie reklamowe r\u00f3\u017cnych firm si\u0119 pomyl\u0105, to b\u0119dzie co\u015b niejasnego. <\/p>\n<p><\/p>\n<p>Jest prosty trik. Prawda, nie za bardzo nadaje si\u0119 do powa\u017cnych danych, ale je\u015bli co\u015b nie jest zbyt powa\u017cne, po prostu dodaj do klucza s\u0142ownika jeszcze identyfikator klienta. Wtedy b\u0119d\u0105 kolizje, ale tylko w obr\u0119bie jednego klienta. Taki spos\u00f3b stosujemy do mapy link\u00f3w w Yandex.Metrica. Mamy tam URL-e, przechowujemy hashe. Wiemy, \u017ce kolizje oczywi\u015bcie si\u0119 zdarzaj\u0105. Jednak kiedy wy\u015bwietla si\u0119 strona, prawdopodobie\u0144stwo, \u017ce na jednej stronie u jednego u\u017cytkownika jakie\u015b URL-e si\u0119 zlepiaj\u0105 i \u017ce to jeszcze zostanie zauwa\u017cone, mo\u017cna zignorowa\u0107. <\/p>\n<p><\/p>\n<p>Jako bonus \u2013 do wielu operacji wystarcz\u0105 same hashe, a same ci\u0105gi mo\u017cna nigdzie nie przechowywa\u0107. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/abbb73aaba29d10e3b7e7650bf68e6a6.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Inny przyk\u0142ad, je\u015bli ci\u0105gi s\u0105 kr\u00f3tkie, na przyk\u0142ad domeny stron. Mo\u017cna je przechowywa\u0107 takimi, jakie s\u0105. Lub, na przyk\u0142ad, j\u0119zyk przegl\u0105darki ru \u2013 2 bajty. Oczywi\u015bcie, szkoda mi tych bajt\u00f3w, ale nie martw si\u0119, 2 bajty to niewielka strata. Prosz\u0119, przechowuj je tak, jak s\u0105, nie przejmuj si\u0119. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/901eaed0029da6ea59630b57ccf80c25.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Inny przypadek, gdy jest bardzo du\u017co ci\u0105g\u00f3w i przy tym wiele unikalnych, a tak\u017ce wiele potencjalnie nieograniczonych. Typowym przyk\u0142adem s\u0105 frazy wyszukiwania lub URL-e. Frazy wyszukiwania, w tym z powodu liter\u00f3wek. Sprawd\u017amy, ile unikalnych fraz wyszukiwania generuje si\u0119 dziennie. Okazuje si\u0119, \u017ce s\u0105 niemal po\u0142ow\u0105 wszystkich wydarze\u0144. W takim przypadku mo\u017cesz pomy\u015ble\u0107, \u017ce trzeba znormalizowa\u0107 dane, obliczy\u0107 identyfikatory i z\u0142o\u017cy\u0107 do osobnej tabeli. Ale nie r\u00f3b tego. Po prostu przechowuj te ci\u0105gi tak, jak s\u0105. <\/p>\n<p><\/p>\n<p>Lepiej \u2013 nie wymy\u015blaj nic, bo je\u015bli b\u0119dziesz przechowywa\u0107 osobno, to b\u0119dziesz musia\u0142 wykona\u0107 join. A ten join \u2013 w najlepszym razie to dost\u0119p losowy do pami\u0119ci, je\u015bli uda si\u0119 to w og\u00f3le za\u0142adowa\u0107 do pami\u0119ci. Je\u015bli si\u0119 nie zmie\u015bci, b\u0119d\u0105 naprawd\u0119 powa\u017cne problemy. <\/p>\n<p><\/p>\n<p>A je\u015bli dane s\u0105 przechowywane w in place, to po prostu odczytywane s\u0105 w odpowiedniej kolejno\u015bci z systemu plik\u00f3w i wszystko jest w porz\u0105dku.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/15f1d632083def16ccbc939579c1cf6b.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Je\u015bli masz URL-e lub jakiekolwiek inne d\u0142ugie, skomplikowane ci\u0105gi, warto pomy\u015ble\u0107 o tym, \u017ce mo\u017cna obliczy\u0107 jak\u0105\u015b wycink\u0119 z g\u00f3ry i zapisa\u0107 j\u0105 w osobnej kolumnie. <\/p>\n<p><\/p>\n<p>Na przyk\u0142ad mo\u017cna osobno przechowywa\u0107 domen\u0119 dla URL-i. I je\u015bli naprawd\u0119 potrzebujesz domeny, po prostu u\u017cyj tej kolumny, a URL-e b\u0119d\u0105 le\u017ce\u0107 i nawet nie b\u0119dziesz ich dotyka\u0107. <\/p>\n<p><\/p>\n<p>Zobaczmy, jaka jest r\u00f3\u017cnica. W ClickHouse istnieje specjalizowana funkcja, kt\u00f3ra oblicza domen\u0119. Jest bardzo szybka, zoptymalizowali\u015bmy j\u0105. I szczerze m\u00f3wi\u0105c, nie spe\u0142nia ona standardu RFC, ale mimo to liczy wszystko, co potrzebujemy. <\/p>\n<p><\/p>\n<p>W jednym przypadku po prostu b\u0119dziemy wyci\u0105ga\u0107 URL-e i oblicza\u0107 domen\u0119. Zajmuje to 166 milisekund. A je\u015bli we\u017amiemy gotow\u0105 domen\u0119, to zajmie to zaledwie 67 milisekund, czyli prawie trzy razy szybciej. Co wi\u0119cej, szybciej nie z powodu konieczno\u015bci przeprowadzania oblicze\u0144, lecz dlatego, \u017ce odczytujemy mniej danych. <\/p>\n<p><\/p>\n<p>Ciekawe, \u017ce w przypadku jednego zapytania, kt\u00f3re jest wolniejsze, jest wi\u0119ksza pr\u0119dko\u015b\u0107 w gigabajtach na sekund\u0119. Dzieje si\u0119 tak, poniewa\u017c odczytuje wi\u0119cej gigabajt\u00f3w. To zupe\u0142nie zb\u0119dne dane. Zapytanie dzia\u0142a szybciej, ale zajmuje wi\u0119cej czasu.<\/p>\n<p><\/p>\n<p>A je\u015bli spojrze\u0107 na obj\u0119to\u015b\u0107 danych na dysku, to okazuje si\u0119, \u017ce URL ma 126 megabajt\u00f3w, a domena zaledwie 5 megabajt\u00f3w. To 25 razy mniej. Mimo to zapytanie wykonuje si\u0119 tylko 4 razy szybciej. Ale to dlatego, \u017ce dane s\u0105 gor\u0105ce. Gdyby by\u0142y zimne, by\u0142oby na pewno 25 razy szybciej z powodu operacji wej\u015bcia-wyj\u015bcia na dysku. <\/p>\n<p><\/p>\n<p>Swoj\u0105 drog\u0105, je\u015bli oceni\u0107, jak bardzo domena jest mniejsza od URL-a, to wynosi gdzie\u015b oko\u0142o 4 razy. Ale jako\u015b na dysku dane zajmuj\u0105 25 razy mniej. Dlaczego? Z powodu kompresji. I URL jest kompresowany, i domena jest kompresowana. Ale cz\u0119sto URL zawiera mn\u00f3stwo \u015bmieci. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/c93d2128a41561ed7abb25d77414bc2d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Oczywi\u015bcie warto u\u017cywa\u0107 odpowiednich typ\u00f3w danych, kt\u00f3re s\u0105 specjalnie przeznaczone do wymaganych warto\u015bci lub kt\u00f3re s\u0105 odpowiednie. Je\u015bli korzystasz z IPv4, przechowuj UInt32*. Je\u015bli z IPv6, to FixedString(16), poniewa\u017c adres IPv6 to 128 bit\u00f3w, a wi\u0119c przechowuj go w formacie binarnym. <\/p>\n<p><\/p>\n<p>A co zrobi\u0107, je\u015bli czasami masz adresy IPv4, a czasami IPv6? Tak, mo\u017cna przechowywa\u0107 oba. Jedna kolumna dla IPv4, druga dla IPv6. Oczywi\u015bcie jest opcja, aby IPv4 zamienia\u0107 na IPv6. To r\u00f3wnie\u017c zadzia\u0142a, ale je\u015bli w zapytaniach cz\u0119sto potrzebujesz konkretnie adresu IPv4, dobrze by\u0142oby umie\u015bci\u0107 go w osobnej kolumnie. <\/p>\n<p><\/p>\n<p>* teraz w ClickHouse istniej\u0105 oddzielne typy danych dla IPv4, IPv6, kt\u00f3re przechowuj\u0105 dane r\u00f3wnie wydajnie, jak liczby, ale prezentuj\u0105 je w r\u00f3wnie wygodny spos\u00f3b, jak ci\u0105gi.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/d7d6342ebd6b8b4f3526b3cd8a06cf26.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Wa\u017cne jest r\u00f3wnie\u017c zauwa\u017cy\u0107, \u017ce warto dane wst\u0119pnie przetworzy\u0107. Na przyk\u0142ad, je\u015bli do ciebie trafiaj\u0105 jakie\u015b surowe logi. Mo\u017ce warto nie wrzuca\u0107 ich od razu do ClickHouse, chocia\u017c bardzo kusi, by nic nie robi\u0107 i wszystko dzia\u0142a\u0142o. Ale warto przeprowadzi\u0107 te obliczenia, kt\u00f3re mo\u017cna.<\/p>\n<p><\/p>\n<p>Na przyk\u0142ad wersja przegl\u0105darki. W pewnym s\u0105siednim dziale, na kt\u00f3ry nie chc\u0119 wskazywa\u0107 palcem, wersja przegl\u0105darki jest przechowywana w ten spos\u00f3b, tzn. jako ci\u0105g znak\u00f3w: 12.3. A nast\u0119pnie, aby wygenerowa\u0107 raport, dziel\u0105 ten ci\u0105g na tablic\u0119, a potem na pierwszy element tablicy. Oczywi\u015bcie wszystko zwalnia. Pyta\u0142em, dlaczego tak robi\u0105. Odpowiedzieli mi, \u017ce nie lubi\u0105 przedwczesnej optymalizacji. A ja nie lubi\u0119 przedwczesnej pesymizacji.<\/p>\n<p><\/p>\n<p>Zatem w tym przypadku lepiej b\u0119dzie podzieli\u0107 dane na 4 kolumny. Nie b\u00f3jcie si\u0119 tego, poniewa\u017c to ClickHouse. ClickHouse to baza danych kolumnowa. Im wi\u0119cej starannie przygotowanych ma\u0142ych kolumn, tym lepiej. B\u0119dzie 5 BrowserVersion, r\u00f3bcie 5 kolumn. To normalne. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/f9a67221bf8508933d7bd336b16f9e04.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Teraz rozwa\u017cmy, co zrobi\u0107, je\u015bli macie du\u017co bardzo d\u0142ugich ci\u0105g\u00f3w, bardzo d\u0142ugich tablic. Nie nale\u017cy ich w og\u00f3le przechowywa\u0107 w ClickHouse. Zamiast tego mo\u017cna w ClickHouse zapisa\u0107 tylko jaki\u015b identyfikator. A te d\u0142ugie ci\u0105gi wrzu\u0107cie do jakiego\u015b innego systemu. <\/p>\n<p><\/p>\n<p>Na przyk\u0142ad, w jednym z naszych serwis\u00f3w analitycznych s\u0105 pewne parametry zdarze\u0144. I je\u015bli dla zdarze\u0144 przychodzi wiele parametr\u00f3w, po prostu przechowujemy pierwsze 512, kt\u00f3re si\u0119 trafi. Bo 512 \u2013 nie jest szkoda. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/755271e8788ba4bd638f493bf320c820.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>A je\u015bli nie jeste\u015bcie pewni swoich typ\u00f3w danych, to mo\u017cecie tak\u017ce zapisa\u0107 dane w ClickHouse, ale w tabeli tymczasowej typu Log, specjalnej do danych tymczasowych. Nast\u0119pnie mo\u017cecie przeanalizowa\u0107, jakie macie tam rozk\u0142ady warto\u015bci, co w og\u00f3le jest i ustali\u0107 poprawne typy.<\/p>\n<p><\/p>\n<p>* obecnie w ClickHouse jest typ danych <noindex><a rel=\"nofollow\" href=\"https:\/\/clickhouse.tech\/docs\/en\/sql-reference\/data-types\/lowcardinality\/\">LowCardinality<\/a><\/noindex> kt\u00f3ry pozwala efektywnie przechowywa\u0107 ci\u0105gi z mniejszymi kosztami obliczeniowymi.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/7e9e53d86a4189783c28ce56a669198c.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Teraz rozwa\u017cmy jeszcze jeden interesuj\u0105cy przypadek. Czasami u ludzi wszystko dzia\u0142a jako\u015b dziwnie. Wchodz\u0119 i widz\u0119 co\u015b takiego. Od razu wyobra\u017cam sobie, \u017ce zrobi\u0142 to jaki\u015b bardzo do\u015bwiadczony, m\u0105dry administrator, kt\u00f3ry ma du\u017ce do\u015bwiadczenie w konfigurowaniu MySQL w wersji 3.23. <\/p>\n<p><\/p>\n<p>Tutaj widzimy tysi\u0105c tabel, w ka\u017cdej z nich zapisany jest reszta z dzielenia nie wiadomo czego przez tysi\u0105c. <\/p>\n<p><\/p>\n<p>W zasadzie szanuj\u0119 cudze do\u015bwiadczenie, a tak\u017ce rozumiem, przez jakie cierpienia mo\u017ce by\u0107 to do\u015bwiadczenie zdobywane. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/3a5e21ef2076966fcc627670485c5b3a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>I przyczyny s\u0105 mniej wi\u0119cej jasne. To stare stereotypy, kt\u00f3re mog\u0142y si\u0119 nagromadzi\u0107 w pracy z innymi systemami. Na przyk\u0142ad w tabelach MyISAM nie ma klastrowanego klucza podstawowego. Taki spos\u00f3b podzia\u0142u danych mo\u017ce by\u0107 rozpaczliw\u0105 pr\u00f3b\u0105 uzyskania tej samej funkcjonalno\u015bci. <\/p>\n<p><\/p>\n<p>Inny pow\u00f3d to trudno\u015bci zwi\u0105zane z przeprowadzaniem operacji typu alter na du\u017cych tabelach. Wszystko b\u0119dzie zablokowane. Chocia\u017c w nowoczesnych wersjach MySQL ten problem nie jest ju\u017c tak powa\u017cny. <\/p>\n<p><\/p>\n<p>Albo na przyk\u0142ad mikroszardowanie, ale o tym troch\u0119 p\u00f3\u017aniej.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/321b1d9caa8db7aca5b96e08c61d05b5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>W ClickHouse nie trzeba tego robi\u0107, poniewa\u017c, po pierwsze, klucz podstawowy jest klastrowany, a dane s\u0105 uporz\u0105dkowane wed\u0142ug klucza podstawowego. <\/p>\n<p><\/p>\n<p>Czasami pytaj\u0105 mnie: \"Jak zmienia si\u0119 wydajno\u015b\u0107 zapyta\u0144 zakresowych w ClickHouse w zale\u017cno\u015bci od rozmiaru tabeli?\" M\u00f3wi\u0119, \u017ce w \u017caden spos\u00f3b si\u0119 nie zmienia. Na przyk\u0142ad, je\u015bli masz tabel\u0119 miliard\u00f3w wierszy i odczytujesz zakres jednego miliona wierszy, wszystko jest w porz\u0105dku. Je\u015bli w tabeli jest trylion wierszy i odczytujesz milion wierszy, to b\u0119dzie niemal to samo. <\/p>\n<p><\/p>\n<p>Po drugie, nie potrzebujesz r\u00f3\u017cnych rzeczy typu r\u0119czne partycjonowanie. Je\u015bli wejdziesz i zajrzysz, co tam jest w systemie plik\u00f3w, zobaczysz, \u017ce tabela to do\u015b\u0107 powa\u017cna sprawa. I tam w \u015brodku jest co\u015b w rodzaju partycji. To znaczy, \u017ce ClickHouse robi wszystko za Ciebie i nie musisz cierpie\u0107.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/652f3742ad3a44f172d0d7302abd09f6.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Alter w ClickHouse jest bezp\u0142atny, je\u015bli chodzi o alter add\/drop column. <\/p>\n<p><\/p>\n<p>I nie warto tworzy\u0107 ma\u0142ych tabel, poniewa\u017c je\u015bli masz tabel\u0119 z 10 wierszami lub 10 000 wierszy, to jest ca\u0142kowicie nieistotne. ClickHouse to system, kt\u00f3ry optymalizuje throughput, a nie latency, wi\u0119c przetwarzanie 10 wierszy nie ma sensu. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/144144b4740e9c5daec80c8dadc445f9.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Prawid\u0142owo jest u\u017cywa\u0107 jednej du\u017cej tabeli. Pozb\u0105d\u017a si\u0119 starych stereotyp\u00f3w, wszystko b\u0119dzie dobrze. <\/p>\n<p><\/p>\n<p>A jako bonus w naszej najnowszej wersji pojawi\u0142a si\u0119 mo\u017cliwo\u015b\u0107 tworzenia dowolnego klucza partycjonowania, aby m\u00f3c przeprowadza\u0107 r\u00f3\u017cne operacje konserwacyjne na pojedynczych partycjach. <\/p>\n<p><\/p>\n<p>Na przyk\u0142ad, potrzebujesz wielu ma\u0142ych tabel, na przyk\u0142ad, gdy zachodzi potrzeba przetwarzania jakich\u015b po\u015brednich danych, otrzymujesz fragmenty i musisz na nich przeprowadza\u0107 transformacje przed zapisaniem do tabeli docelowej. W tym przypadku jest wspania\u0142y silnik tabeli \u2013 StripeLog. To jest co\u015b jak TinyLog, tylko lepsze. <\/p>\n<p><\/p>\n<p>* teraz w ClickHouse jest tak\u017ce <noindex><a rel=\"nofollow\" href=\"https:\/\/clickhouse.tech\/docs\/en\/sql-reference\/table-functions\/input\/\">funkcja tabelaryczna input<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/d62f0b3d29876c29c6c0ba236b200186.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Kolejnym antywzorem jest mikrodzielnie. Na przyk\u0142ad, musisz podzieli\u0107 dane i masz 5 serwer\u00f3w, a jutro b\u0119dzie 6 serwer\u00f3w. Zastanawiasz si\u0119, jak te dane przerebalansowa\u0107. Zamiast tego dzielisz je nie na 5 shard\u00f3w, a na 1 000 shard\u00f3w. A nast\u0119pnie przypisujesz ka\u017cdy z tych mikrodzielnik\u00f3w do oddzielnego serwera. I oka\u017ce si\u0119, \u017ce na jednym serwerze b\u0119dzie 200 ClickHouse, na przyk\u0142ad. Oddzielne instancje na oddzielnych portach lub oddzielne bazy danych. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/3e550ef7e338b84e4394eb9fa4538769.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ale w ClickHouse to nie jest zbyt dobre. Poniewa\u017c nawet jeden instancja ClickHouse stara si\u0119 wykorzysta\u0107 wszystkie dost\u0119pne zasoby serwera do przetwarzania jednego zapytania. Tzn. masz jaki\u015b serwer i na przyk\u0142ad 56 rdzeni procesora. Wykonujesz zapytanie, kt\u00f3re trwa jedn\u0105 sekund\u0119 i wykorzysta 56 rdzeni. A je\u015bli umie\u015bcisz tam 200 ClickHouse na jednym serwerze, to uruchomi si\u0119 10 000 w\u0105tk\u00f3w. W skr\u00f3cie, wszystko b\u0119dzie bardzo \u017ale.<\/p>\n<p><\/p>\n<p>Innym powodem jest to, \u017ce rozk\u0142ad pracy pomi\u0119dzy te instancje b\u0119dzie nier\u00f3wnomierny. Niekt\u00f3re zako\u0144cz\u0105 wcze\u015bniej, inne p\u00f3\u017aniej. Gdyby wszystko dzia\u0142o si\u0119 w jednym instancji, to ClickHouse sam by sobie poradzi\u0142 z odpowiednim rozk\u0142adem danych pomi\u0119dzy w\u0105tki. <\/p>\n<p><\/p>\n<p>I jeszcze jednym powodem jest to, \u017ce b\u0119dzie mi\u0119dzyprocesowa komunikacja przez TCP. Dane b\u0119d\u0105 musia\u0142y by\u0107 serializowane, deserializowane i to olbrzymia liczba mikrodzielnik\u00f3w. Po prostu b\u0119dzie to nieefektywne.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/18cacc17d22ae1cb2977c6be74769896.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Kolejnym antywzorem, cho\u0107 trudno go nazwa\u0107 antywzorem, jest du\u017ca liczba wst\u0119pnej agregacji.<\/p>\n<p><\/p>\n<p>Og\u00f3lnie rzecz bior\u0105c, wst\u0119pna agregacja to co\u015b dobrego. Mia\u0142e\u015b miliard wierszy, zgrupowa\u0142e\u015b je i sta\u0142o si\u0119 1 000 wierszy, a teraz zapytanie wykonuje si\u0119 natychmiast. Wszystko jest wspania\u0142e. Mo\u017cna tak robi\u0107. A w tym celu nawet w ClickHouse jest specjalny typ tabeli AggregatingMergeTree, kt\u00f3ry wykonuje inkrementaln\u0105 agregacj\u0119 podczas wstawiania danych. <\/p>\n<p><\/p>\n<p>S\u0105 jednak sytuacje, gdy my\u015blisz, \u017ce b\u0119dziemy agregowa\u0107 dane w ten spos\u00f3b i jeszcze tak. A w pewnym s\u0105siednim dziale, kt\u00f3rego nazwiska nie chc\u0119 podawa\u0107, u\u017cywaj\u0105 tabel SummingMergeTree do sumowania wed\u0142ug klucza g\u0142\u00f3wnego, u\u017cywaj\u0105c jako klucza g\u0142\u00f3wnego oko\u0142o 20 r\u00f3\u017cnych kolumn. Dla ostro\u017cno\u015bci zmieni\u0142em nazwy niekt\u00f3rych kolumn, ale wygl\u0105da to mniej wi\u0119cej tak.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/54e3a02ab4bbce7c63ded595780ae1f6.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>I pojawiaj\u0105 si\u0119 pewne problemy. Po pierwsze, obj\u0119to\u015b\u0107 danych nie zmniejsza si\u0119 zbytnio. Na przyk\u0142ad zmniejsza si\u0119 trzykrotnie. Trzykrotne zmniejszenie to by\u0142aby dobra cena, by pozwoli\u0107 sobie na nieograniczone mo\u017cliwo\u015bci analityki, kt\u00f3re pojawiaj\u0105 si\u0119, gdy dane nie s\u0105 agregowane. Je\u015bli dane s\u0105 agregowane, to zamiast analityki otrzymujesz jedynie marn\u0105 statystyk\u0119. <\/p>\n<p><\/p>\n<p>Co szczeg\u00f3lnie irytuje? To, \u017ce ludzie z s\u0105siedniego dzia\u0142u przychodz\u0105 i czasami prosz\u0105 o dodanie jeszcze jednej kolumny do klucza g\u0142\u00f3wnego. Tzn. tak agregowali\u015bmy dane, a teraz chcemy troch\u0119 wi\u0119cej. Ale w ClickHouse nie ma mo\u017cliwo\u015bci zmiany klucza g\u0142\u00f3wnego. Dlatego trzeba pisa\u0107 jakie\u015b skrypty w C++. A ja nie lubi\u0119 skrypt\u00f3w, nawet je\u015bli s\u0105 w C++.<\/p>\n<p><\/p>\n<p>Je\u015bli spojrzysz, do czego stworzono ClickHouse, to nieagregowane dane to dok\u0142adnie ten scenariusz, dla kt\u00f3rego zosta\u0142 stworzony. Je\u015bli u\u017cywasz ClickHouse do nieagregowanych danych, to robisz wszystko dobrze. Je\u015bli agregujesz, to to czasami mo\u017cna wybaczy\u0107. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/09fafd4c8a3ea8c22e586cb7a5cf6564.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Jeszcze jeden interesuj\u0105cy przypadek \u2013 to zapytania w niesko\u0144czonej p\u0119tli. Czasem wchodz\u0119 na jaki\u015b serwer produkcyjny i patrz\u0119 na show processlist. I za ka\u017cdym razem odkrywam, \u017ce dzieje si\u0119 co\u015b strasznego. <\/p>\n<p><\/p>\n<p>Na przyk\u0142ad co\u015b takiego. Od razu wida\u0107, \u017ce wszystko mog\u0142o by\u0107 wykonane w jednym zapytaniu. Wystarczy wpisa\u0107 tam url in i list\u0119.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/ae03b659f178962f50e0640614517296.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Dlaczego tak wiele zapyta\u0144 w niesko\u0144czonej p\u0119tli jest z\u0142e? Je\u015bli indeks nie jest u\u017cywany, b\u0119dzie wiele przej\u015b\u0107 przez te same dane. Ale je\u015bli indeks jest u\u017cywany, na przyk\u0142ad masz klucz g\u0142\u00f3wny wed\u0142ug ru i wpisujesz url = co\u015b tam. I my\u015blisz, \u017ce b\u0119dzie czytane punktowo z tabeli jeden url, wszystko b\u0119dzie w porz\u0105dku. Ale w rzeczywisto\u015bci nie. Poniewa\u017c ClickHouse robi to wszystko w paczkach. <\/p>\n<p><\/p>\n<p>Kiedy potrzebuje odczyta\u0107 jaki\u015b zakres danych, odczytuje troch\u0119 wi\u0119cej, poniewa\u017c indeks w ClickHouse jest rozrzedzony. Ten indeks nie pozwala znale\u017a\u0107 w tabeli jednej pojedynczej linii, tylko jaki\u015b zakres. Dane s\u0105 kompresowane w blokach. Aby odczyta\u0107 jedn\u0105 lini\u0119, trzeba wzi\u0105\u0107 ca\u0142y blok i go rozpakowa\u0107. A je\u015bli wykonujesz wiele zapyta\u0144, b\u0119dziesz mia\u0142 wiele powt\u00f3rze\u0144 takich i mn\u00f3stwo pracy b\u0119dzie wykonywane raz po raz.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/95eef43c5b869f8b145c61ce3c616cfd.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Jako bonus mo\u017cna zauwa\u017cy\u0107, \u017ce w ClickHouse nie warto si\u0119 ba\u0107 przesy\u0142ania nawet megabajt\u00f3w, a nawet setek megabajt\u00f3w do sekcji IN. Pami\u0119tam z naszej praktyki, \u017ce je\u015bli w MySQL przesy\u0142amy mn\u00f3stwo warto\u015bci do sekcji IN, na przyk\u0142ad przesy\u0142amy tam 100 megabajt\u00f3w jakich\u015b liczb, to MySQL zu\u017cywa 10 gigabajt\u00f3w pami\u0119ci i nic wi\u0119cej si\u0119 nie dzieje, wszystko dzia\u0142a s\u0142abo. <\/p>\n<p><\/p>\n<p>A drug\u0105 rzecz\u0105 jest to, \u017ce w ClickHouse, je\u015bli twoje zapytania wykorzystuj\u0105 indeks, to zawsze nie jest wolniejsze ni\u017c pe\u0142ne skanowanie, tzn. je\u015bli trzeba odczyta\u0107 prawie ca\u0142\u0105 tabel\u0119, b\u0119dzie to robi\u0142o sekwencyjnie i odczyta ca\u0142\u0105 tabel\u0119. W og\u00f3lnym uj\u0119ciu samo si\u0119 ogarnie.<\/p>\n<p><\/p>\n<p>Jednak pojawiaj\u0105 si\u0119 pewne trudno\u015bci. Na przyk\u0142ad to, \u017ce IN z podzapytaniem nie wykorzystuje indeksu. Ale to nasz problem i musimy to naprawi\u0107. Nic fundamentalnego tutaj nie ma. B\u0119dziemy to naprawia\u0107. <\/p>\n<p><\/p>\n<p>I jeszcze jedna ciekawa rzecz \u2013 to, \u017ce je\u015bli masz bardzo d\u0142ugie zapytanie i rozproszon\u0105 obr\u00f3bk\u0119 zapyta\u0144, to to bardzo d\u0142ugie zapytanie b\u0119dzie wysy\u0142ane do ka\u017cdego serwera bez kompresji. Na przyk\u0142ad, 100 megabajt\u00f3w i 500 serwer\u00f3w. I odpowiednio, przez sie\u0107 zostanie przes\u0142ane 50 gigabajt\u00f3w. Zostanie przes\u0142ane, a potem wszystko zostanie pomy\u015blnie wykonane.<\/p>\n<p><\/p>\n<p>* ju\u017c u\u017cywa; wszystko naprawione, jak obiecano.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/5fcde9bf04fff0645be2530daa12743f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>I do\u015b\u0107 cz\u0119stym przypadkiem jest, gdy zapytania przychodz\u0105 z API. Na przyk\u0142ad, stworzy\u0142e\u015b jaki\u015b sw\u00f3j serwis. I je\u015bli tw\u00f3j serwis jest komu\u015b potrzebny, otworzy\u0142e\u015b API i dos\u0142ownie po dw\u00f3ch dniach widzisz, \u017ce dzieje si\u0119 co\u015b dziwnego. Wszystko jest przeci\u0105\u017cone i przychodz\u0105 jakie\u015b okropne zapytania, kt\u00f3re nigdy nie powinny by\u0142y si\u0119 pojawi\u0107. <\/p>\n<p><\/p>\n<p>I rozwi\u0105zanie jest jedno. Je\u015bli otworzy\u0142e\u015b API, to b\u0119dziesz musia\u0142 wprowadzi\u0107 ograniczenia. Na przyk\u0142ad, wprowadzi\u0107 jakie\u015b kwoty. Innych normalnych opcji nie ma. W przeciwnym razie od razu napisz\u0105 skrypt i b\u0119d\u0105 problemy. <\/p>\n<p><\/p>\n<p>W ClickHouse istnieje specjalna funkcja - to jest liczenie kwot. Mo\u017cna przekaza\u0107 w\u0142asny klucz kwoty, na przyk\u0142ad wewn\u0119trzny identyfikator u\u017cytkownika. Kwoty b\u0119d\u0105 liczone niezale\u017cnie dla ka\u017cdego z nich. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/532438d0f116919e62f04e32ebbd3c45.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Teraz jeszcze jedna interesuj\u0105ca rzecz. To replikacja na nap\u0119dzie r\u0119cznym. <\/p>\n<p><\/p>\n<p>Znam wiele przypadk\u00f3w, kiedy, mimo \u017ce ClickHouse ma wbudowan\u0105 obs\u0142ug\u0119 replikacji, ludzie replikuj\u0105 ClickHouse r\u0119cznie.<\/p>\n<p><\/p>\n<p>Jaki jest zasadniczy pomys\u0142? Macie pipeline do przetwarzania danych, kt\u00f3ry dzia\u0142a niezale\u017cnie, na przyk\u0142ad w r\u00f3\u017cnych centrach danych. Zapisujecie te same dane w ten sam spos\u00f3b do ClickHouse. Prawda jest taka, \u017ce praktyka pokazuje, i\u017c dane i tak b\u0119d\u0105 si\u0119 r\u00f3\u017cni\u0107 z powodu jakich\u015b specyficznych cech w waszym kodzie. Mam nadziej\u0119, \u017ce w waszym przypadku tak nie b\u0119dzie. <\/p>\n<p><\/p>\n<p>I od czasu do czasu i tak b\u0119dziecie musieli zsynchronizowa\u0107 r\u0119cznie. Na przyk\u0142ad raz w miesi\u0105cu administratorzy wykonuj\u0105 rsync.<\/p>\n<p><\/p>\n<p>W rzeczywisto\u015bci znacznie \u0142atwiej jest u\u017cy\u0107 wbudowanej replikacji ClickHouse. Ale mog\u0105 pojawi\u0107 si\u0119 pewne przeciwwskazania, poniewa\u017c do tego trzeba korzysta\u0107 z ZooKeeper. Nic z\u0142ego nie powiem o ZooKeeper, generalnie system dzia\u0142a, ale bywa, \u017ce ludzie go nie u\u017cywaj\u0105 z powodu fobii przed Java, poniewa\u017c ClickHouse to bardzo dobra system napisana w C++, z kt\u00f3rego mo\u017cna korzysta\u0107 bez problem\u00f3w. A ZooKeeper jest na Javie. I jako\u015b nie chce si\u0119 nawet na to patrze\u0107, wi\u0119c wtedy mo\u017cna u\u017cy\u0107 replikacji na nap\u0119dzie r\u0119cznym. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/3b5b68996daef6b8920f067b189f25e0.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>ClickHouse to praktyczny system. Uwzgl\u0119dnia twoje potrzeby. Je\u015bli masz replikacj\u0119 na nap\u0119dzie r\u0119cznym, mo\u017cesz stworzy\u0107 tabel\u0119 rozproszon\u0105, kt\u00f3ra patrzy na twoje r\u0119czne repliki i automatycznie wykonuje failover mi\u0119dzy nimi. Istnieje nawet specjalna opcja, kt\u00f3ra pozwala unikn\u0105\u0107 fluktuacji, nawet je\u015bli twoje repliki systematycznie si\u0119 r\u00f3\u017cni\u0105.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/70f6630f8b14756163923a7db8dd7391.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Mog\u0105 wyst\u0105pi\u0107 problemy, je\u015bli u\u017cywasz prymitywnych silnik\u00f3w tabel. ClickHouse to taka konstrukcja, kt\u00f3ra ma wiele r\u00f3\u017cnych silnik\u00f3w tabel. Do wszystkich powa\u017cnych przypadk\u00f3w, jak napisano w dokumentacji, u\u017cywaj tabel z rodziny MergeTree. A wszystkie inne - to tak, do wyj\u0105tkowych przypadk\u00f3w lub do test\u00f3w.<\/p>\n<p><\/p>\n<p>W tabeli MergeTree nie jest konieczne, aby mie\u0107 jak\u0105\u015b dat\u0119 i czas. W ka\u017cdym razie mo\u017cesz z tego skorzysta\u0107. Je\u015bli nie ma daty i czasu, wpisz, \u017ce domy\u015blnie to rok 2000. To b\u0119dzie dzia\u0142a\u0107 i nie b\u0119dzie wymaga\u0107 zasob\u00f3w. <\/p>\n<p><\/p>\n<p>W nowej wersji serwera mo\u017cna nawet okre\u015bli\u0107, \u017ce chcesz mie\u0107 niestandardowe partycjonowanie bez klucza partycji. To b\u0119dzie to samo. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/6d4046d11afdd1e5962d49a1612b666a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Z drugiej strony, mo\u017cna u\u017cywa\u0107 prymitywnych silnik\u00f3w tabel. Na przyk\u0142ad, za\u0142aduj dane raz i zobacz, pokr\u0119\u0107 i usu\u0144 je. Mo\u017cesz u\u017cywa\u0107 Log.<\/p>\n<p><\/p>\n<p>Lub przechowywanie ma\u0142ych obj\u0119to\u015bci do przetwarzania po\u015bredniego \u2013 to StripeLog lub TinyLog.<\/p>\n<p><\/p>\n<p>Mo\u017cna u\u017cywa\u0107 pami\u0119ci, je\u015bli obj\u0119to\u015b\u0107 danych jest ma\u0142a i po prostu co\u015b pokr\u0119\u0107 w pami\u0119ci operacyjnej. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/8a3d4e0e3a8c26dd3a2b2f64123e2bf9.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>ClickHouse nie za bardzo lubi dane z nadmiern\u0105 normalizacj\u0105. <\/p>\n<p><\/p>\n<p>Oto typowy przyk\u0142ad. To ogromna liczba URLi. W\u0142o\u017cy\u0142e\u015b je do s\u0105siedniej tabeli. A potem zdecydowa\u0142e\u015b si\u0119 na JOIN, ale to nie zadzia\u0142a, poniewa\u017c ClickHouse obs\u0142uguje tylko Hash JOIN. Je\u015bli brakuje pami\u0119ci operacyjnej dla du\u017cej ilo\u015bci danych, kt\u00f3re trzeba po\u0142\u0105czy\u0107, to JOIN nie b\u0119dzie mo\u017cliwy. <\/p>\n<p><\/p>\n<p>Je\u015bli dane maj\u0105 du\u017c\u0105 kardynalno\u015b\u0107, to nie przejmuj si\u0119, przechowuj je w denormalizowanej formie, URL-e bezpo\u015brednio w g\u0142\u00f3wnej tabeli. <\/p>\n<p><\/p>\n<p>* A teraz w ClickHouse jest r\u00f3wnie\u017c merge join, kt\u00f3ry dzia\u0142a w sytuacjach, gdy dane po\u015brednie nie mieszcz\u0105 si\u0119 w pami\u0119ci operacyjnej. Jednak jest to nieefektywne i zalecenie pozostaje w mocy.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/e8160a8db17c18d48f810092c55b094c.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Jeszcze kilka przyk\u0142ad\u00f3w, ale ju\u017c mam w\u0105tpliwo\u015bci, czy s\u0105 one antywzorcowe. <\/p>\n<p><\/p>\n<p>ClickHouse ma jeden znany minus. Nie obs\u0142uguje aktualizacji. W pewnym sensie to nawet dobrze. Je\u015bli masz jakie\u015b wa\u017cne dane, na przyk\u0142ad ksi\u0119gowo\u015b\u0107, nikt ich nie wy\u015ble, poniewa\u017c nie ma aktualizacji.<\/p>\n<p><\/p>\n<p>* Od d\u0142u\u017cszego czasu dodano obs\u0142ug\u0119 aktualizacji i usuwania w trybie wsadowym.<\/p>\n<p><\/p>\n<p>S\u0105 jednak pewne specjalne sposoby, kt\u00f3re pozwalaj\u0105 na aktualizacje jakby w tle. Na przyk\u0142ad, tabele typu ReplaceMergeTree. Dokonuj\u0105 aktualizacji podczas t\u0142a \u0142\u0105cz\u0105cego. Mo\u017cesz to wymusi\u0107 za pomoc\u0105 optymalizacji tabeli. Ale nie r\u00f3b tego za cz\u0119sto, poniewa\u017c b\u0119dzie to pe\u0142ne przepisanie partycji. <\/p>\n<p><\/p>\n<p>Rozproszone JOIN w ClickHouse r\u00f3wnie\u017c s\u0105 \u017ale obs\u0142ugiwane przez planner zapyta\u0144. <\/p>\n<p><\/p>\n<p>\u0179le, ale czasem w porz\u0105dku.<\/p>\n<p><\/p>\n<p>U\u017cywanie ClickHouse tylko po to, aby odczyta\u0107 dane z powrotem za pomoc\u0105 select.<\/p>\n<p><\/p>\n<p>Nie poleca\u0142bym u\u017cywania ClickHouse do rozbudowanych oblicze\u0144. Ale to nie do ko\u0144ca prawda, poniewa\u017c ju\u017c odchodzimy od tej rekomendacji. Ostatnio dodali\u015bmy mo\u017cliwo\u015b\u0107 stosowania modeli uczenia maszynowego w ClickHouse \u2013 Catboost. To mnie martwi, bo my\u015bl\u0119 sobie: \u201eJaki straszny widok. Ile\u017c to cykli na bajt!\u201d. Bardzo mi \u017cal wydawa\u0107 cykle na bajty. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Efektywne wykorzystanie ClickHouse. Aleksiej Mi\u0142owidow (Yandex)\" src=\"\/wp-content\/uploads\/2020\/08\/f686d5d352ccb444cd06e2ae68897137.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ale nie b\u00f3jcie si\u0119, instalujcie ClickHouse, wszystko b\u0119dzie dobrze. W razie czego, mamy spo\u0142eczno\u015b\u0107. A tak przy okazji, spo\u0142eczno\u015b\u0107 to wy. I je\u015bli macie jakie\u015b problemy, mo\u017cecie przynajmniej zajrze\u0107 na nasz czat, i mam nadziej\u0119, \u017ce wam pomog\u0105. <\/p>\n<p><\/p>\n<p>Pytania<\/p>\n<p><\/p>\n<p><em>Dzi\u0119kuj\u0119 za prezentacj\u0119! Gdzie mog\u0119 zg\u0142osi\u0107 awari\u0119 ClickHouse?<\/em><\/p>\n<p><\/p>\n<p>Mo\u017cecie zg\u0142asza\u0107 to do mnie osobi\u015bcie ju\u017c teraz. <\/p>\n<p><\/p>\n<p><em>Niedawno zacz\u0105\u0142em u\u017cywa\u0107 ClickHouse. Od razu pad\u0142 interfejs cli.<\/em><\/p>\n<p><\/p>\n<p>Mia\u0142e\u015b szcz\u0119\u015bcie. <\/p>\n<p><\/p>\n<p><em>Chwil\u0119 p\u00f3\u017aniej r\u00f3wnie\u017c zniszczy\u0142em serwer ma\u0142ym selectem.<\/em><\/p>\n<p><\/p>\n<p>Masz talent. <\/p>\n<p><\/p>\n<p><em>Zg\u0142osi\u0142em b\u0142\u0105d na GitHubie, ale go zignorowano.<\/em> <\/p>\n<p><\/p>\n<p>Zobaczymy. <\/p>\n<p><\/p>\n<p><em>Aleksiej oszuka\u0142 mnie, \u017ceby zaci\u0105gn\u0105\u0107 na prezentacj\u0119, obiecuj\u0105c opowiedzie\u0107, jak kompresujecie dane wewn\u0119trznie.<\/em><\/p>\n<p><\/p>\n<p>Bardzo prosto. <\/p>\n<p><\/p>\n<p><em>To zrozumia\u0142em ju\u017c wczoraj. Potrzebuj\u0119 wi\u0119cej konkret\u00f3w.<\/em> <\/p>\n<p><\/p>\n<p>Nie ma tam \u017cadnych strasznych sztuczek. To po prostu kompresja po blokach. Domy\u015blnie u\u017cywa si\u0119 LZ4, ale mo\u017cna w\u0142\u0105czy\u0107 ZSTD*. Bloki maj\u0105 od 64 kilobajt\u00f3w do 1 megabajta.<\/p>\n<p><\/p>\n<p>* istnieje r\u00f3wnie\u017c wsparcie dla wyspecjalizowanych kodek\u00f3w kompresji, kt\u00f3re mo\u017cna u\u017cywa\u0107 w \u0142a\u0144cuchu z innymi algorytmami.<\/p>\n<p><\/p>\n<p><em>W blokach s\u0105 po prostu surowe dane?<\/em><\/p>\n<p><\/p>\n<p>Nie do ko\u0144ca surowe. S\u0105 tam tablice. Je\u015bli macie kolumn\u0119 liczbow\u0105, to liczby s\u0105 u\u0142o\u017cone kolejno w tablicy. <\/p>\n<p><\/p>\n<p><em>Rozumiem.<\/em> <\/p>\n<p><\/p>\n<p><em>Aleksiej, przyk\u0142ad, kt\u00f3ry mia\u0142e\u015b z uniqExact nad adresami IP, to znaczy, \u017ce uniqExact jest wolniejszy dla ci\u0105g\u00f3w ni\u017c dla liczb itd. A co je\u015bli zastosujemy sztuczk\u0119 i przekonwertujemy w momencie odczytu? To znaczy, wydaje mi si\u0119, \u017ce m\u00f3wili\u015bcie, \u017ce na dysku to nie r\u00f3\u017cni si\u0119 zbytnio. Je\u015bli b\u0119dziemy czyta\u0107 z dysku ci\u0105gi, konwertowa\u0107, to wtedy nasze agregaty b\u0119d\u0105 szybsze, czy nie? A mo\u017ce jednak nieznacznie zyskamy? Wydaje mi si\u0119, \u017ce testowali\u015bcie to, ale jako\u015b nie zaznaczyli\u015bcie w benchmarkach.<\/em> <\/p>\n<p><\/p>\n<p>My\u015bl\u0119, \u017ce b\u0119dzie to wolniejsze ni\u017c bez kasty. W takim przypadku trzeba sparsowa\u0107 adres IP z ci\u0105gu. Oczywi\u015bcie, w ClickHouse r\u00f3wnie\u017c mamy zoptymalizowane parsowanie adres\u00f3w IP. Bardzo si\u0119 starali\u015bmy, ale macie tam liczby zapisane w formie dziesi\u0119ciotysi\u0119cznej. Bardzo niewygodne. Z drugiej strony funkcja uniqExact b\u0119dzie dzia\u0142a\u0107 na ci\u0105gach wolniej nie tylko dlatego, \u017ce to ci\u0105gi, ale tak\u017ce dlatego, \u017ce wybierana jest inna specjalizacja algorytmu. Ci\u0105gi po prostu s\u0105 przetwarzane inaczej.<\/p>\n<p><\/p>\n<p><em>A co, je\u015bli we\u017amiemy bardziej prymitywny typ danych? Na przyk\u0142ad, zapisali\u015bmy user id, kt\u00f3ry mamy w, zapisali\u015bmy go jako ci\u0105g, a potem go skastowali\u015bmy, czy b\u0119dzie to lepsze, czy nie?<\/em><\/p>\n<p><\/p>\n<p>W\u0105tpi\u0119. My\u015bl\u0119, \u017ce b\u0119dzie nawet gorzej, poniewa\u017c parsowanie liczb to powa\u017cny problem. Wydaje mi si\u0119, \u017ce ten kolega mia\u0142 nawet prezentacj\u0119 na temat trudno\u015bci w parsowaniu liczb w formie dziesi\u0119ciotysicznej, a mo\u017ce i nie. <\/p>\n<p><\/p>\n<p><em>Alieksei, bardzo dzi\u0119kuj\u0119 za prezentacj\u0119! I jeszcze raz dzi\u0119kuj\u0119 za ClickHouse! Mam pytanie dotycz\u0105ce plan\u00f3w. Czy jest planowana funkcja aktualizacji s\u0142ownik\u00f3w nie w ca\u0142o\u015bci?<\/em><\/p>\n<p><\/p>\n<p>Tzn. cz\u0119\u015bciowe prze\u0142adowanie?<\/p>\n<p><\/p>\n<p><em>Tak-tak. Typu mo\u017cliwo\u015b\u0107 ustawienia tam pola MySQL, tzn. aktualizowa\u0107 po, aby \u0142adowa\u0107 tylko te dane, je\u015bli s\u0142ownik jest bardzo du\u017cy.<\/em><\/p>\n<p><\/p>\n<p>Bardzo interesuj\u0105ca funkcja. Wydaje mi si\u0119, \u017ce jaka\u015b osoba proponowa\u0142a j\u0105 na naszym czacie. Mo\u017ce to nawet by\u0142e\u015b ty. <\/p>\n<p><\/p>\n<p><em>Nie s\u0105dz\u0119, \u017cebym to by\u0142 ja.<\/em><\/p>\n<p><\/p>\n<p>\u015awietnie, teraz wychodzi, \u017ce s\u0105 dwa zapytania. I mo\u017cna powoli zaczyna\u0107 to robi\u0107. Ale od razu chc\u0119 was ostrzec, \u017ce ta funkcja jest do\u015b\u0107 prosta do zaimplementowania. Tzn. w zasadzie trzeba po prostu zapisa\u0107 w tabeli numer wersji i pisa\u0107: wersja jest mniejsza ni\u017c taka. A to oznacza, \u017ce najprawdopodobniej zaproponujemy to zrobi\u0107 entuzjastom. Czy jeste\u015b entuzjast\u0105? <\/p>\n<p><\/p>\n<p><em>Tak, ale niestety nie w C++.<\/em><\/p>\n<p><\/p>\n<p>Czy wasi koledzy potrafi\u0105 pisa\u0107 w C++? <\/p>\n<p><\/p>\n<p><em>Zaraz kogo\u015b znajd\u0119.<\/em><\/p>\n<p><\/p>\n<p>\u015awietnie*.<\/p>\n<p><\/p>\n<p>* mo\u017cliwo\u015b\u0107 zosta\u0142a dodana dwa miesi\u0105ce po prezentacji \u2013 zosta\u0142a opracowana przez autora pytania i przes\u0142ana <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/ClickHouse\/ClickHouse\/pull\/1771\">pull request<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p><em>Dzi\u0119kuj\u0119!<\/em><\/p>\n<p><\/p>\n<p><em>Cze\u015b\u0107! Dzi\u0119kuj\u0119 za prezentacj\u0119! Wspomina\u0142e\u015b, \u017ce ClickHouse bardzo dobrze wykorzystuje wszystkie dost\u0119pne mu zasoby. A prelegent obok z Luxoft m\u00f3wi\u0142 o swoim rozwi\u0105zaniu dla Poczty Rosyjskiej. Powiedzia\u0142, \u017ce bardzo im si\u0119 spodoba\u0142 ClickHouse, ale nie u\u017cyli go zamiast swojego g\u0142\u00f3wnego konkurenta, w\u0142a\u015bnie dlatego, \u017ce zu\u017cywa\u0142 ca\u0142y procesor. I nie mogli go w\u0142\u0105czy\u0107 w swoj\u0105 architektur\u0119, w swojego ZooKeepera z dockerami. Czy jest mo\u017cliwo\u015b\u0107 jako\u015b ograniczy\u0107 ClickHouse, aby nie zu\u017cywa\u0142 wszystkiego, co mu si\u0119 udost\u0119pnia?<\/em><\/p>\n<p><\/p>\n<p>Tak, mo\u017cna to zrobi\u0107 i jest to bardzo proste. Je\u015bli chcesz, aby u\u017cywa\u0142 mniej rdzeni, napisz po prostu <code>set max_threads = 1<\/code>. I wszystko, b\u0119dzie wykonywa\u0142 zapytania na jednym rdzeniu. Mo\u017cna zreszt\u0105 r\u00f3\u017cnym u\u017cytkownikom ustawi\u0107 r\u00f3\u017cne te parametry. Wi\u0119c nie ma problemu. A kolegom z Luxoft przeka\u017c, \u017ce nie dobrze, \u017ce nie znale\u017ali tej opcji w dokumentacji. <\/p>\n<p><\/p>\n<p><em>Aleksiej, cze\u015b\u0107! Chcia\u0142em zada\u0107 takie pytanie. Ju\u017c nie po raz pierwszy s\u0142ysz\u0119, \u017ce wielu zaczyna u\u017cywa\u0107 ClickHouse jako magazyn na logi. Na prezentacji m\u00f3wi\u0142e\u015b, \u017ceby tego nie robi\u0107, tzn. nie nale\u017cy przechowywa\u0107 d\u0142ugich linii. Jak si\u0119 do tego odnosisz?<\/em><\/p>\n<p><\/p>\n<p>Po pierwsze, logi to z regu\u0142y nie s\u0105 d\u0142ugie linie. Oczywi\u015bcie bywaj\u0105 wyj\u0105tki. Na przyk\u0142ad, jaki\u015b serwis pisany w javie, zg\u0142asza wyj\u0105tek, kt\u00f3ry jest logowany. I tak w niesko\u0144czonej p\u0119tli, i ko\u0144czy si\u0119 miejsce na dysku twardym. Rozwi\u0105zanie jest bardzo proste. Je\u015bli linie s\u0105 bardzo d\u0142ugie, to je tnij. A co to znaczy d\u0142ugie? Dziesi\u0105tki kilobajt\u00f3w \u2013 to \u017ale.<\/p>\n<p><\/p>\n<p>* w najnowszych wersjach ClickHouse wprowadzono \"adaptacyjne granulowanie indeks\u00f3w\", co w du\u017cej mierze rozwi\u0105zuje problem przechowywania d\u0142ugich \u0142a\u0144cuch\u00f3w.<\/p>\n<p><\/p>\n<p><em>A kilobajt \u2013 to w porz\u0105dku?<\/em><\/p>\n<p><\/p>\n<p>W porz\u0105dku. <\/p>\n<p><\/p>\n<p><em>Cze\u015b\u0107! Dzi\u0119kuj\u0119 za prezentacj\u0119! Ju\u017c o to pyta\u0142em na czacie, ale nie pami\u0119tam, czy otrzyma\u0142em odpowied\u017a. Czy planuje si\u0119 jako\u015b rozszerzy\u0107 sekcj\u0119 WITH na wz\u00f3r CTE?<\/em><\/p>\n<p><\/p>\n<p>Na razie nie. Sekcja WITH to dla nas co\u015b niezbyt powa\u017cnego. To dla nas taka ma\u0142a funkcja.<\/p>\n<p><\/p>\n<p><em>Rozumiem. Dzi\u0119kuj\u0119!<\/em><\/p>\n<p><\/p>\n<p><em>Dzi\u0119kuj\u0119 za prezentacj\u0119! Bardzo interesuj\u0105co! Mam globalne pytanie. Czy planujecie mo\u017ce wprowadzenie jakich\u015b mechanizm\u00f3w do usuwania danych?<\/em><\/p>\n<p><\/p>\n<p>Oczywi\u015bcie. To nasze pierwsze zadanie w kolejce. Aktualnie intensywnie my\u015blimy, jak wszystko zrobi\u0107 poprawnie. I czas zacz\u0105\u0107 stuka\u0107 w klawiatur\u0119.<\/p>\n<p><\/p>\n<p>* naciskali\u015bmy przyciski na klawiaturze i wszystko zrobili\u015bmy.<\/p>\n<p><\/p>\n<p><em>Czy to wp\u0142ynie jako\u015b na wydajno\u015b\u0107 systemu? Czy wstawianie b\u0119dzie tak samo szybkie, jak teraz?<\/em><\/p>\n<p><\/p>\n<p>Mo\u017cliwe, \u017ce same usuni\u0119cia i aktualizacje b\u0119d\u0105 bardzo ci\u0119\u017ckie, ale nie wp\u0142ynie to na wydajno\u015b\u0107 zapyta\u0144 selektywnych i wstawianie.<\/p>\n<p><\/p>\n<p><em>I jeszcze jedno ma\u0142e pytanie. Na prezentacji m\u00f3wi\u0142e\u015b o kluczu g\u0142\u00f3wnym. Mamy zatem partycjonowanie, kt\u00f3re jest domy\u015blnie miesi\u0119czne, prawda? Kiedy okre\u015blamy zakres dat, kt\u00f3ry mie\u015bci si\u0119 w miesi\u0105cu, to odczytywana jest tylko ta partycja, prawda?<\/em><\/p>\n<p><\/p>\n<p>Tak.<\/p>\n<p><\/p>\n<p><em>Takie pytanie. Je\u015bli nie mo\u017cemy wydzieli\u0107 \u017cadnego klucza g\u0142\u00f3wnego, to czy s\u0142usznie by\u0142oby zrobi\u0107 go na podstawie pola \u201eData\u201d, aby w tle by\u0142a mniejsza reorganizacja tych danych, by by\u0142y uporz\u0105dkowane? Je\u017celi nie masz zapyta\u0144 zakresowych i nie mo\u017cesz wybra\u0107 \u017cadnego klucza g\u0142\u00f3wnego, czy warto umie\u015bci\u0107 dat\u0119 w kluczu g\u0142\u00f3wnym?<\/em><\/p>\n<p><\/p>\n<p>Tak.<\/p>\n<p><\/p>\n<p>Mo\u017ce warto umie\u015bci\u0107 w kluczu g\u0142\u00f3wnym takie pole, po kt\u00f3rym dane b\u0119d\u0105 lepiej si\u0119 kompresowa\u0107, je\u015bli b\u0119d\u0105 posortowane wed\u0142ug tego pola. Na przyk\u0142ad, identyfikator u\u017cytkownika. U\u017cytkownik, na przyk\u0142ad, odwiedza t\u0119 sam\u0105 stron\u0119. W tym przypadku umieszczasz ID u\u017cytkownika i czas. Wtedy dane b\u0119d\u0105 lepiej si\u0119 kompresowa\u0107. Je\u017celi chodzi o dat\u0119, je\u015bli naprawd\u0119 nie masz i nigdy nie masz zapyta\u0144 zakresowych po datach, to mo\u017cesz nie umieszcza\u0107 daty w kluczu g\u0142\u00f3wnym. <\/p>\n<p><\/p>\n<p><em>Dzi\u0119kuj\u0119 bardzo!<\/em><\/p>\n<p>\u0179r\u00f3d\u0142o: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/514840\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0422\u0430\u043a \u043a\u0430\u043a ClickHouse \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u043e\u0439, \u043f\u0440\u0438 \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u0432\u0430\u0436\u043d\u043e \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u0435\u0433\u043e \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b. \u0412 \u044d\u0442\u043e\u043c \u0434\u043e\u043a\u043b\u0430\u0434\u0435 \u0410\u043b\u0435\u043a\u0441\u0435\u0439 \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0435\u0442 \u043e \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445 \u0442\u0438\u043f\u0438\u0447\u043d\u044b\u0445 \u043e\u0448\u0438\u0431\u043e\u043a \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 ClickHouse, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u043f\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u043a \u043d\u0435\u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u0435. \u041d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445 \u0438\u0437 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0438 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u043e, \u043a\u0430\u043a \u0432\u044b\u0431\u043e\u0440 \u0442\u043e\u0439 \u0438\u043b\u0438 \u0438\u043d\u043e\u0439 \u0441\u0445\u0435\u043c\u044b \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u043c\u043e\u0436\u0435\u0442 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043d\u0430 \u043f\u043e\u0440\u044f\u0434\u043a\u0438. \u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442! \u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":91439,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-91438","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.1.1 - aioseo.com -->\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/effektivnoe-ispolzovanie-clickhouse-aleksej-milovidov-yandeks\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"pl_PL\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u042d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 ClickHouse. \u0410\u043b\u0435\u043a\u0441\u0435\u0439 \u041c\u0438\u043b\u043e\u0432\u0438\u0434\u043e\u0432 (\u042f\u043d\u0434\u0435\u043a\u0441) | ProHoster\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/effektivnoe-ispolzovanie-clickhouse-aleksej-milovidov-yandeks\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-08-13T17:42:36+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-08-13T17:42:36+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Efektywne wykorzystanie ClickHouse. Aleksey Milovidov (Yandex) | ProHoster","description":"","canonical_url":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/effektivnoe-ispolzovanie-clickhouse-aleksej-milovidov-yandeks","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"pl_PL","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u042d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 ClickHouse. \u0410\u043b\u0435\u043a\u0441\u0435\u0439 \u041c\u0438\u043b\u043e\u0432\u0438\u0434\u043e\u0432 (\u042f\u043d\u0434\u0435\u043a\u0441) | ProHoster","og:url":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/effektivnoe-ispolzovanie-clickhouse-aleksej-milovidov-yandeks","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-08-13T17:42:36+00:00","article:modified_time":"2020-08-13T17:42:36+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"91438","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 12:27:23","updated":"2022-09-28 17:25:41","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts\/91438","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/comments?post=91438"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts\/91438\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/media\/91439"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/media?parent=91438"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/categories?post=91438"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/tags?post=91438"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}