ClickHouse для прасунутых карыстальнікаў у пытаннях і адказах

У красавіку інжынеры Авіта збіраліся на анлайн-вячоркі з галоўным распрацоўшчыкам ClickHouse Аляксеем Мілавідавым і Кірылам Шваковым, Golang-распрацоўшчыкам з кампаніі Integros. Абмяркоўвалі, як мы выкарыстоўваем сістэму кіравання базамі даных і якія складанасці ў нас узнікаюць.

Па матывах сустрэчы мы сабралі артыкул з адказамі экспертаў на нашы і пытанні гледачоў пра бэкапы, решардинг дадзеных, знешнія слоўнікі, Golang-драйвер і абнаўленне версій ClickHouse. Яна можа быць карысная распрацоўшчыкам, якія ўжо актыўна працуюць з СКБД "Яндэкса" і цікавяцца яе сучаснасцю і будучыняй. Па змаўчанні адказы Аляксея Мілавідава, калі не напісана іншае.

Асцярожна, пад катом шмат тэксту. Спадзяемся, што змест з пытаннямі дапаможа вам зарыентавацца.

ClickHouse для прасунутых карыстальнікаў у пытаннях і адказах

Змест

Калі не жадаецца чытаць тэкст, можна паглядзець запіс вячорак на нашым ютуб-канале. Таймкоды - у першым каментары пад відэа.

ClickHouse пастаянна абнаўляецца, а нашы дадзеныя - не. Што з гэтым рабіць?

ClickHouse пастаянна абнаўляецца, а нашы дадзеныя, якія былі optimize final апрацаваны, не абнаўляюцца і ляжаць у рэзервовай копіі.

Дапусцім, у нас здарылася якая-небудзь праблема, і дадзеныя былі згубленыя. Мы вырашылі аднавіцца, і аказалася, што старыя партіціі, якія ляжаць на захаванні ў серверах бэкапаў, вельмі моцна разыходзяцца з выкарыстоўванай на дадзены момант версіяй ClickHouse. Што рабіць у такой сітуацыі, і ці магчымая яна?

Сітуацыя, пры якой вы аднавілі з бэкапу дадзеныя ў старым фармаце, а на новай версіі яны не падключаюцца, немагчыма. Мы сочым за тым, каб фармат дадзеных у ClickHouse заўсёды заставаўся зваротна сумяшчальным. Гэта значна важней, чым зваротная сумяшчальнасць па функцыянальнасці, калі змяніліся паводзіны нейкай рэдка выкарыстоўванай функцыі. Дадзеныя, якія захоўваюцца на дыску, новая версія ClickHouse заўсёды павінен умець чытаць. Гэта закон.

Якія лепшыя практыкі ёсць на дадзены момант па рэзервовым капіяванні дадзеных з ClickHouse?

Як рабіць рэзервовыя копіі з тым улікам, што ў нас ёсць аперацыі optimize final, вялізная база дадзеных на тэрабайты, і дадзеныя, якія абнаўляюцца, выкажам здагадку, за апошнія тры дні, а далей з імі ніякіх працэдур не адбываецца?

Мы можам накастыляць уласнае рашэнне і на вежы напісаць: збірай вось так і вось гэтыя рэзервовыя копіі. Можа быць, кастыляць нічога не трэба, і ровар даўно вынайдзены?

Для пачатку наконт лепшых практык. Мае калегі заўсёды раяць у адказ на пытанні пра бэкапы нагадваць пра сэрвіс «Яндэкс.Хмара», дзе гэтая задача ўжо вырашана. Так што карыстайцеся ім, калі ёсьць такая магчымасьць.

Поўнага рашэння, цалкам убудаванага ў ClickHouse, для бэкапаў няма. Ёсць некаторыя нарыхтоўкі, якія можна выкарыстоўваць. Каб атрымаць поўнае рашэнне, прыйдзецца альбо крыху ўручную павазіцца, альбо зрабіць абгорткі ў выглядзе скрыптоў.

Пачну з самых простых рашэнняў і скончу самымі наварочанымі ў залежнасці ад аб'ёму дадзеных і памеру кластара. Чым больш кластар - тым складаней становіцца рашэнне.

Калі табліца з дадзенымі займае ўсяго некалькі гігабайт, бэкап можна зрабіць так:

  1. Захаваць вызначэнне табліц, гэта значыць метададзеныя - show create table.
  2. Зрабіць дамп з дапамогай ClickHouse кліента выбраць * from table у файл. Па змаўчанні вы атрымаеце файл у фармаце TabSeparated. Калі хочацца больш эфектыўна - можна ў фармаце Native.

Калі аб'ём дадзеных большы, то бэкап зойме больш часу і шмат месца. Гэта называецца лагічны бэкап, ён не прывязаны да фармату дадзеных ClickHouse. Калі ён ёсць, то ў крайнім выпадку вы зможаце ўзяць бэкап і загрузіць у MySQL для аднаўлення.

Для больш прасунутых выпадкаў у ClickHouse убудавана магчымасць стварыць снапшот партыцый у лакальнай файлавай сістэме. Гэтая магчымасць даступна ў выглядзе запыту alter table freeze partition. Або проста alter table freeze - Гэта снапшот ўсёй табліцы.

Снапшот будзе створаны кансістэнтным для адной табліцы на адным шардзе, гэта значыць стварыць кансістэнтны снапшот усяго кластара такім чынам немагчыма. Але для большасці задач такой неабходнасці няма, і дастаткова на кожным шардзе выканаць запыт і атрымаць кансістэнтны снапшот. Ён ствараецца ў выглядзе хардлінкаў і таму не займае дадатковага месца. Далей гэты снапшот вы капіруеце на бэкап-сервер або ў сховішча, якое выкарыстоўваеце для бэкапаў.

Аднавіць такі бэкап дастаткова лёгка. Першае - ствараеце табліцы па наяўных азначэннях табліц. Далей капіруеце захаваныя снапшоты партыцый у Directory-Detached для дадзеных табліц і выконваеце запыт attach partition. Такое рашэнне суцэль падыходзіць для самых сур'ёзных аб'ёмаў дадзеных.

Часам патрабуецца нешта яшчэ страмчэй - у тых выпадках, калі ў вас дзясяткі ці нават сотні тэрабайт на кожным серверы і сотні сервераў. Тут ёсць рашэнне, якое я падгледзеў у калегаў з "Яндэкс.Метрыкі". Я б не рэкамендаваў яго кожнаму - прачытайце і самі вырашыце, падыходзіць яно ці не.

Спачатку трэба стварыць некалькі сервераў з вялікімі дыскавымі паліцамі. Далей на гэтых серверах падняць некалькі ClickHouse сервераў і наладзіць іх так, каб яны працавалі як яшчэ адна рэпліка для тых жа шардов. І далей выкарыстоўваць на гэтых серверах файлавую сістэму або нейкую прыладу, які дазваляе ствараць снапшоты. Тут ёсць два варыянты. Першы варыянт – гэта LVM снапшоты, другі варыянт – ZFS на Linux.

Пасля гэтага кожны дзень трэба ствараць снапшот, ён будзе ляжаць і займаць нейкае месца. Натуральна, калі дадзеныя мяняюцца, то з часам аб'ём месца будзе павялічвацца. Гэты снапшот можна дастаць у любы момант і аднавіць дадзеныя, вось такое дзіўнае рашэнне. Плюс яшчэ трэба абмежаваць гэтыя рэплікі ў канфігу, каб яны не спрабавалі станавіцца лідарамі.

Ці можна будзе арганізаваць кантраляванае адставанне рэплік у валах?

У гэтым годзе вы плануеце рабіць валы ў ClickHouse. Ці можна будзе ў іх арганізаваць кантраляванае адставанне рэплік? Мы хацелі б з яго дапамогай засцерагчы сябе ад негатыўных сцэнарыяў з альтэрамі і іншымі зменамі.

Ці можна зрабіць нейкія roll back для альтэраў? Напрыклад, у існуючым вале ўзяць і сказаць, што да гэтага моманту ўжывай змены, а з гэтага моманту змены перастань ужываць?

Калі ў наш кластар прыйшла каманда і паламала яго, то ў нас ёсць умоўная рэпліка з адставаннем у гадзіну, дзе мы можам сказаць, што давайце будзем менавіта яе выкарыстоўваць на дадзены момант, але апошнія дзесяць хвілін змен у ёй прымяняць не будзем?

Для пачатку пра кантраляванае адставанне рэплік. Такі запыт ад карыстальнікаў быў, і мы стварылі issue на Гітхабе з просьбай: "Калі камусьці гэта трэба, стаўце лайк, стаўце сэрца". Ніхто не паставіў, і issue закрылі. Тым не менш, ужо зараз можна атрымаць такую ​​магчымасць, наладзіўшы ClickHouse. Праўда, толькі пачынаючы з версіі 20.3/XNUMX.

ClickHouse увесь час у фоне вырабляе зліццё дадзеных – мердж. Калі мердж выраблены, некаторы набор кавалкаў дадзеных замяняецца на буйнейшы кавалак. Пры гэтым кавалкі дадзеных, якія былі раней, працягваюць заставацца на дыску на працягу некаторага часу.

Па-першае, яны працягваюць захоўвацца да таго часу, пакуль ёсць запыты select, якія іх выкарыстоўваюць, для таго каб забяспечыць неблакіруючую працу. Запыты select спакойна чытаюць са старых кавалкаў.

Па-другое, ёсць яшчэ і парог па часе - старыя кавалкі дадзеных ляжаць на дыску восем хвілін. Гэтыя восем хвілін можна наладзіць і ператварыць нават у адзін дзень. Гэта будзе каштаваць месцы на дыску: у залежнасці ад патоку дадзеных атрымаецца, што за апошні дзень дадзеныя не тое што падвояцца, іх можа стаць у пяць разоў больш. Але вы зможаце пры сур'ёзнай праблеме спыніць ClickHouse сервер і з усім разабрацца.

Цяпер узнікае пытанне, як гэта абараняе ад альтэраў. Тут варта паглядзець глыбей, таму што ў старых версіях ClickHouse альтэр працаваў такім чынам, што проста непасрэдна мяняў кавалкі. Ёсць кавалак дадзеных з нейкімі файламі, і мы робім, напрыклад, alter drop column. Тады гэты слупок фізічна выдаляецца з усіх кавалкаў.

Але пачынаючы з версіі 20.3, механізм альтэраў быў цалкам зменены, і зараз кавалкі дадзеных заўсёды імутабельныя. Яны не змяняюцца наогул - альтэры зараз працуюць прыкладна гэтак жа, як Мерджы. Замест таго, каб мяняць кавалак на месцы, мы ствараем новы. У новым кавалку файлы, якія не змяніліся, становяцца хардлінкамі, і, калі мы выдалілі нейкі слупок, ён проста будзе адсутнічаць у новым кавалку. Стары кавалак выдаліцца па змаўчанні праз восем хвілін, і тут можна падкруціць наладкі, аб якіх сказана вышэй.

Тое ж тычыцца альтэраў тыпу мутацый. Калі вы робіце alter delete або alter update, ён не змяняе кавалак, а стварае новы. А потым выдаляе стары.

Як быць, калі структура табліцы памянялася?

Як падняць бэкап, які быў зроблены са старой схемай? І другое пытанне пра кейс са снапшотамі і сродкамі файлавай сістэмы. Ці падыходзіць тут Btrfs замест ZFS на Linux LVM?

Калі вы робіце attach partition партыцыі з іншай структурай, то ClickHouse вам скажа, што так нельга. Рашэнне такое. Першае - стварыць часовую табліцу тыпу MergeTree са старой структурай, прычапіць туды дадзеныя з дапамогай attach, зрабіць запыт alter. Потым можна альбо скапіяваць ці перанесці гэтыя дадзеныя і зрабіць attach зноў, альбо выкарыстоўваць запыт alter table move partition.

Цяпер другое пытанне - ці можна выкарыстоўваць Btrfs. Для пачатку, калі ў вас ёсць LVM, то дастаткова LVM снапшотаў, а файлавая сістэма можа быць і ext4, гэта не мае значэння. З Btrts усё залежыць ад вашага досведу яе эксплуатацыі. Гэта спелая файлавая сістэма, але ўсё роўна ўзнікаюць некаторыя падазрэнні наконт таго, як усё адпрацуе на практыцы ў канкрэтным сцэнары. Я б не раіў гэта выкарыстоўваць, калі ў вас няма Btrfs ў прадакшне.

Якія зараз лепшыя практыкі ў решардинге дадзеных?

Пытанне пра перашардзіраванне складанае і шматграннае. Тут можна адказаць адразу некалькімі варыянтамі. Можна зайсці з аднаго боку і сказаць так – у ClickHouse убудаванай магчымасці перешардирования няма. Але я баюся, гэты адказ нікога не задаволіць. Таму можна зайсці з іншага боку і сказаць, што ў ClickHouse ёсць шмат спосабаў перашардзіравання дадзеных.

Калі сканчаецца месца на кластары ці ён не спраўляецца з нагрузкай, вы дадаеце новыя серверы. Але гэтыя серверы па змаўчанні пустыя, дадзеных на іх няма, нагрузкі ніякай не ідзе. Вам трэба перакласці дадзеныя, каб яны сталі раўнамерна размазаны па новым, павялічанаму ў памерах, кластару.

Першы спосаб, якім гэта можна зрабіць, - гэта скапіяваць частку партыцый на новыя серверы з дапамогай запыту. alter table fetch partition. Напрыклад, былі ў вас партыцыі па месяцах, і вы бераце першы месяц 2017 года і капіюеце на новы сервер, потым - трэці месяц капіюеце на нейкі яшчэ новы сервер. І так робіце, пакуль не стане больш-менш раўнамерна.

Перанос можна ажыццяўляць толькі для тых партыцый, якія не мяняюцца пры запісе. Для свежых партыцый запіс давядзецца адключыць, таму што іх перанос не атамарны. Інакш вы атрымаеце дублікаты ці пропускі ў дадзеных. Тым не менш, гэты спосаб практычны і працуе дастаткова эфектыўна. Па сетцы перадаюцца ўжо гатовыя сціснутыя партіціі, гэта значыць дадзеныя не пераціскаюцца і не перакадуюцца.

У гэтага спосабу ёсць адзін недахоп, і ён залежыць ад схемы шардзіравання, ці закладваліся вы на гэтую схему шардзіравання, які ў вас быў ключ шардзіравання. У вашым прыкладзе для выпадку з метрыкамі ключ шардзіравання - гэта хэш ад шляху. Калі ў вас ідзе select у Distributed табліцу, ён ідзе адразу на ўсе шарды кластара і забірае адтуль дадзеныя.

Гэта значыць, што практычна вам не мае значэння, якія дадзеныя на якім шардзе апынуліся. Галоўнае тое, што дадзеныя па адным шляху аказваюцца на адным шардзе, а вось якім менавіта, не прынцыпова. У гэтым выпадку перанос гатовых партыцый выдатна падыходзіць, таму што пры запытах select вы таксама - што да перашардзіравання, што пасля, схема значэння асабліва не мае - будзеце атрымліваць поўныя дадзеныя.

Але бываюць выпадкі і больш складаныя. Калі на ўзроўні логікі прыкладання вы закладваецеся на спецыяльную схему шардзіравання, што гэты кліент размешчаны на такім-то шардзе, і запыт можна адправіць адразу туды, а не ў Distributed табліцу. Ці вы карыстаецеся дастаткова свежую версію ClickHouse і ўключылі наладу optimize skip unused shards. У гэтым выпадку падчас запыту select выраз у секцыі where будзе прааналізавана, і будзе вылічана, на якія шарды неабходна пайсці паводле схемы шаліравання. Гэта працуе пры ўмове, што дадзеныя раскладзены менавіта ў адпаведнасці з гэтай схемай шардзіравання. Калі вы іх пераклалі ўручную, адпаведнасць можа памяняцца.

Такім чынам, гэта спосаб нумар адзін. І я чакаю вашага адказу, падыходзіць спосаб, ці ідзем далей.

Уладзімір Калабаеў, lead system administrator у Авіта: Аляксей, той спосаб, які вы згадалі, не вельмі добра кладзецца, калі трэба размазаць нагрузку ў тым ліку і на чытанне. Мы можам узяць партыцыю, якая месячная і можам папярэдні месяц панесці на іншую наду, але калі прыйдзе запыт за гэтымі дадзенымі, мы будзем нагружаць толькі яе. А хацелася б нагружаць увесь кластар, таму што, у адваротным выпадку, у нас нейкі час уся нагрузка на чытанне будзе апрацоўвацца двума шардамі.

Аляксей Мілавідаў: Адказ тут дзіўны - так, дрэнна, але можа і пракаціць. Растлумачу, як менавіта. Варта паглядзець на сцэнар нагрузкі, які ідзе за вашымі дадзенымі. Калі гэта дадзеныя маніторынгу, то амаль напэўна можна сказаць, што пераважная большасць запытаў ідзе за свежымі дадзенымі.

Вы паставілі новыя серверы, перанеслі старыя партіціі, але таксама змянілі тое, як запісваюцца свежыя дадзеныя. І свежыя дадзеныя будуць размазаны па ўсім кластары. Такім чынам, ужо праз пяць хвілін запыты за апошнія пяць хвілін будуць раўнамерна нагружаць кластар, праз дзень запыты за суткі будуць раўнамерна нагружаць кластар. А запыты за папярэдні месяц, нажаль, пайдуць толькі на частку сервераў кластара.

Але часта ў вас не будзе запытаў менавіта за люты 2019 года. Хутчэй за ўсё, калі ўжо запыты ідуць у 2019 год, то яны будуць за ўвесь 2019 год - за вялікі інтэрвал часу, а не за нейкую маленькі дыяпазон. І такія запыты таксама змогуць паступова нагрузіць кластар. Але ў цэлым ваша заўвага зусім дакладна, што гэта такое ad hoc рашэнне, якое не размазвае дадзеныя цалкам раўнамерна.

У мяне ёсьць яшчэ некалькі пунктаў для адказу на пытаньне. Адзін з іх пра тое, як першапачаткова зрабіць схему шардзіравання такой, каб ад перашардзіравання было менш болю. Гэта, магчыма, не заўсёды.

Напрыклад, у вас ёсць дадзеныя маніторынгу. Дадзеныя маніторынгу растуць па трох прычынах. Першая - назапашванне гістарычных дадзеных. Другая - рост трафіку. І трэцяя - павелічэнне колькасці тых рэчаў, якія падпадаюць пад маніторынг. З'яўляюцца новыя мікрасэрвісы і метрыкі, якія трэба захоўваць.

Магчыма, што з іх самы вялікі рост звязаны менавіта з трэцяй прычынай - гэта павелічэнне выкарыстання маніторынгу. І у гэтым выпадку варта паглядзець на характар ​​нагрузкі, якія асноўныя запыты на select. Асноўныя запыты на select, хутчэй за ўсё, будуць ісці па некаторым падмностве метрык.

Напрыклад, выкарыстанне CPU на нейкіх серверах нейкім сервісам. Атрымліваецца, што ёсць некаторае падмноства ключоў, па якім вы гэтыя дадзеныя дастаеце. І сам запыт за гэтымі дадзенымі, хутчэй за ўсё, дастаткова просты і выконваецца за дзясяткі мілісекунд. Выкарыстоўваецца для сэрвісаў маніторынгу, для дашбордаў. Спадзяюся, я правільна гэта разумею.

Уладзімір Калабаеў: Справа ў тым, што мы вельмі часта апелюем да гістарычных дадзеных, бо мы ў рэжыме рэальнага часу параўноўваем бягучае становішча з гістарычным. І для нас важна мець хуткі доступ да вялікага аб'ёму дадзеных, і ClickHouse з гэтым выдатна спраўляецца.

Вы абсалютна правы, большасць запытаў на чытанне мы адчуваем за апошні дзень, як і любая сістэма маніторынгу. Але пры гэтым на гістарычныя дадзеныя нагрузка таксама дастаткова вялікая. Яна ў асноўным ад сістэмы алертынгу, якая кожныя XNUMX секунд ходзіць і кажа ClickHouse: «Аддай мне дадзеныя за апошнія шэсць тыдняў. А цяпер пабудуй мне з іх якую-небудзь слізгальную сярэднюю, і давай параўнаем бягучае значэнне з гістарычным».

Я хацеў бы сказаць, што ў нас для такіх вельмі свежых запытаў існуе яшчэ адна маленькая таблічка, у якой мы захоўваем усяго два дні дадзеных, і асноўныя запыты ляцяць у яе. У вялікую шаліраваную табліцу мы адпраўляем толькі вялікія гістарычныя запыты.

Аляксей Мілавідаў: На жаль, для вашага сцэнара атрымліваецца дрэнна дастасавальна, але я раскажу апісанне двух дрэнных і складаных схем шардзіравання, якія не трэба выкарыстоўваць, але якія выкарыстоўваюцца ў сэрвісе маіх сяброў.

Ёсць асноўны кластар з падзеямі "Яндэкс.Метрыкі". Падзеі - гэта прагляды старонак, зграі і пераходы. Большасць запытаў ідзе да канкрэтнага вэб-сайта. Вы адкрываеце сэрвіс «Яндэкс.Метрыка», у вас ёсць сайт — avito.ru, заходзьце ў справаздачу і ідзе запыт па вашым сайце.

Але ёсць і іншыя запыты - аналітычныя і глабальныя, якія робяць унутраныя аналітыкі. На ўсялякі выпадак адзначу, што ўнутраныя аналітыкі робяць запыты толькі па сэрвісах "Яндэкса". Але тым не менш, нават сэрвісы "Яндэкса" займаюць істотную долю ад усіх дадзеных. Гэта запыты не па канкрэтных лічыльніках, а па больш шырокаму фільтраванню.

Як арганізаваць дадзеныя такім чынам, каб і па адным лічыльніку ўсё працавала эфектыўна, і глабальныя запыты таксама? Складанасць яшчэ складаецца ў тым, што колькасць запытаў у ClickHouse на кластар "Метрыкі" – некалькі тысяч у секунду. Пры гэтым нетрывіяльных запытаў, напрыклад, некалькі тысяч у секунду адзін сервер ClickHouse не цягне.

Памер кластара – шэсцьсот з чымсьці сервераў. Калі над гэтым кластарам проста нацягнуць Distributed табліцу і адпраўляць туды некалькі тысяч запытаў, тое стане яшчэ горш, чым адпраўляць іх на адзін сервер. З іншага боку, варыянт з тым, што дадзеныя размазаныя раўнамерна, а мы ідзём і запытваем са ўсіх сервераў, адразу адкідаем.

Ёсць варыянт дыяметральна супрацьлеглы. Уявіце, калі мы дадзеныя будзем шаліць па сайтах, і запыт для аднаго сайта пойдзе на адзін шард. Цяпер кластар цалкам зможа выцягнуць дзесяць тысяч запытаў у секунду, але на адным шардзе нейкі адзін запыт будзе працаваць занадта марудна. Ён ужо не будзе маштабавацца па прапускной здольнасці. Асабліва, калі гэта сайт avito.ru. Я не раскрою сакрэт, калі скажу, што Авіта - гэта адзін з найбольш наведвальных сайтаў у рунэце. І апрацоўваць яго на адным шардзе было б вар'яцтвам.

Таму схема шардзіравання ўладкована больш хітрай выявай. Увесь кластар разбіты на некаторую колькасць кластаркаў, якія мы завем пластамі. Унутры кожнага кластарка ад дзясятка да некалькіх дзясяткаў шардаў. А ўсяго такіх кластаркаў трыццаць дзевяць.

Як гэта ўсё маштабуецца? Колькасць кластаркаў не мяняецца - як было некалькі гадоў таму трыццаць дзевяць, так і засталося. Але ўсярэдзіне кожнага з іх мы паступова павялічваем колькасць шардов па меры назапашвання дадзеных. І схема шардзіравання ў цэлым такая - разбіццё на гэтыя кластаркі ідзе па вэб-сайтах, і для таго каб зразумець, які сайт на якім кластары, выкарыстоўваецца наогул асобная метабаза ў MySQL. Адзін сайт - на адным кластарцы. А ўнутры яго шаліраванне ідзе па ідэнтыфікатарах наведвальнікаў.

Пры запісе мы іх разбіваем па астатку ад дзялення ідэнтыфікатара наведвальніка. Але пры даданні новага шарда схема шардзіравання змяняецца, мы працягваем разбіваць, але пры астатку ад дзялення на іншы лік. Гэта значыць, што адзін наведвальнік ужо ўсё ж такі размешчаны на некалькіх серверах, і закладвацца на гэта нельга. Гэта зроблена выключна для таго, каб дадзеныя лепш сціскаліся. А пры запытах мы ідзем у Distributed табліцу, якая глядзіць на кластарак і звяртаецца да дзясяткаў сервераў. Вось такая дурная схема.

Але маё апавяданне будзе няпоўным, калі я не скажу, што ад гэтай схемы мы адмовіліся. У новай схеме мы ўсё змянілі і ўсе дадзеныя скапіявалі з дапамогай clickhouse-copier.

У новай схеме ўсе сайты дзеляцца на дзве катэгорыі - вялікія і маленькія. Я не ведаю, як там абраны парог, але ў выніку атрымалася так, што вялікія сайты запісваюцца на адзін кластар, дзе 120 шардаў па тры рэплікі ў кожным - гэта значыць 360 сервераў. І схема шардзіравання такая, што любы запыт ідзе адразу на ўсе шарды. Калі вы зараз у «Яндэкс.Метрыцы» адкрыеце любую старонку справаздачы для avito.ru, запыт пойдзе на 120 сервераў. Вялікіх сайтаў у рунэце мала. І запытаў атрымліваецца не тысяча за секунду, а нават менш за сотню. Усё гэта спакойна пражоўвае Distributed табліца, якую кожны з іх апрацоўвае 120 серверамі.

А другі кластар - для маленькіх сайтаў. Тут схема шардзіравання па ідэнтыфікатары сайта, і кожны запыт ідзе роўна на адзін шард.

У ClickHouse ёсць утыліта clickhouse-copier. Можаце пра яе расказаць?

Адразу скажу, што гэтае рашэнне больш грувасткае і некалькі менш прадукцыйнае. Перавага ў тым, што яно размазвае дадзеныя цалкам паводле той схемы, якую вы пакажаце. Але недахоп утыліты ў тым, што яна зусім не робіць перашардзіраванне. Яна капіюе дадзеныя з адной схемы кластара ў іншую схему кластара.

Гэта значыць, што для яе працы ў вас павінна быць два кластары. Яны могуць быць размешчаны на аднолькавых серверах, але, тым не менш, дадзеныя не будуць перамяшчацца інкрыментальна, а будуць скапіяваныя.

Напрыклад, было чатыры серверы, стала восем. Вы ствараеце на ўсіх серверах новую Distributed табліцу, новыя лакальныя табліцы і запускаеце clickhouse-copier, паказваючы ў ім схему працы, што ён павінен чытаць адтуль, прыняць новую схему шаліравання і перакладаць дадзеныя туды. І вам на старых серверах запатрабуецца месцы ў паўтара разу больш, чым ёсць зараз, таму што старыя дадзеныя павінны на іх заставацца, і зверху на іх прыедзе палоўка ад гэтых жа старых дадзеных. Калі вы загадзя падумалі аб тым, што дадзеныя трэба перашардаваць і месца ёсць, то такі спосаб падыдзе.

Як унутры ўладкованы clickhouse-copier? Ён разбівае ўсю працу на набор задач па апрацоўцы адной партыцыі адной табліцы на адным шардзе. Усе гэтыя задачы могуць выконвацца раўналежна, і clickhouse-copier можа быць запушчаны на розных машынах у некалькіх асобніках, але тое, што ён робіць для адной партіціі гэта не што іншае як insert select. Дадзеныя чытаюцца, расціскаюцца, пераразбіваюцца, потым зноў сціскаюцца, запісваюцца кудысьці, перасартуюцца. Гэтае больш цяжкае рашэнне.

У вас была пілотная штука, якая называлася решардинг. Што з ёю?

У вас была яшчэ ў 2017 годзе пілотная штука, якая называлася решардинг. Нават ёсць опцыя ў ClickHouse. Я так разумею, гэта не ўзляцела. Можаце расказаць, чаму так атрымалася? Здаецца вельмі нават актуальна.

Уся праблема ў тым, што пры неабходнасці перашардаваць дадзеныя на месцы патрабуецца вельмі складаная сінхранізацыя для таго, каб зрабіць гэта атамарна. Калі мы сталі глядзець на тое, якім чынам гэтая сінхранізацыя ўладкованая, стала зразумела, што ёсьць фундаментальныя праблемы. І гэтыя фундаментальныя праблемы не толькі тэарэтычныя, але і адразу ж сталі паказваць сябе на практыцы ў выглядзе таго, што можна растлумачыць вельмі проста - нічога не працуе.

Ці можна зліваць усе часткі дадзеных разам перад перамяшчэннем на павольныя дыскі?

Пытанне па TTL з опцыяй move to slow disk у кантэксце мэрджэй. Ці ёсць спосаб, акрамя як па cron, зліваць усе часткі ў адну перад перасоўваннем на павольныя кружэлкі?

Адказ на пытанне, ці можна неяк аўтаматычна склейваць усе кавалкі ў адзін да іх пераносу - не. Мне падаецца, у гэтым няма патрэбы. Можна і не зліваць усе часткі ў адну, а проста разлічваць на тое, што яны будуць пераносіцца на павольныя кружэлкі аўтаматычна.

У нас два крытэры правіл пераносу. Першы - па меры запаўнення. Калі на бягучым узроўні сховішчы менш нейкага адсотка вольнага месца, мы выбіраем адзін кавалак і пераносім яго на павальнейшае сховішча. Дакладней не больш павольнае, а наступнае - як наладзіце.

Другі крытэр - па памеры. Ён пра перанос вялікіх кавалкаў. Вы можаце адрэгуляваць парог па вольным месцы на хуткай кружэлцы, і дадзеныя будуць пераносіцца аўтаматычна.

Як пераязджаць на новыя версіі ClickHouse, калі няма магчымасці загадзя праверыць сумяшчальнасць?

Гэтая тэма рэгулярна абмяркоўваецца у тэлеграм-чаце ClickHouse з улікам розных версій, і ўсё ж. Наколькі бяспечна абнаўляцца з версіі 19.11/19.16 на 19.16 і, напрыклад, з 20.3 на XNUMX. Як лепш пераязджаць на новыя версіі, не маючы магчымасці загадзя праверыць сумяшчальнасць у пясочніцы?

Тут некалькі "залатых" правіл. Першае - чытайце changelog. Ён вялікі, але там ёсць асобныя пункты пра зваротна несумяшчальныя змены. Не варта ставіцца да гэтых пунктаў як да чырвонага сцяга. Звычайна гэта дробныя несумяшчальнасці, якія злучаны з некаторай краявой функцыянальнасцю, якая, суцэль верагодна, у вас не выкарыстоўваецца.

Другое - калі няма магчымасці праверыць сумяшчальнасць у пясочніцы, і вы хочаце абнавіцца адразу ў прадакшне, рэкамендацыя такая - не трэба гэтага рабіць. Спачатку стварыце пясочніцу і праверце. Калі тэставага асяроддзя няма, то ў вас, хутчэй за ўсё, не вельмі вялікая кампанія, а значыць можна скапіяваць частку дадзеных на свой наўтбук і на ім пераканацца, што ўсё карэктна працуе. Можна нават падняць некалькі рэплік лакальна на сваёй машыне. Ці можна дзе-небудзь побач падняць новую версію, і заліць туды частка дадзеных - гэта значыць зрабіць імправізаванае тэставае асяроддзе.

Яшчэ адно правіла - не абнаўляцца на працягу тыдня пасля выхаду версіі па прычыне адлову багаў у прадакшне і наступных хуткіх фіксаў. Давайце разбяромся з нумарацыяй версій ClickHouse, каб не заблытацца.

Ёсць версія 20.3.4. Лік 20 абазначае год выпуску - 2020. З пункту гледжання таго, што ўнутры, гэта ніякага значэння не мае, так што звяртаць увагу на гэта не будзем. Далей - 20.3. Другую лічбу - у дадзеным выпадку 3 - мы павялічваем кожны раз, калі выпускаем рэліз з нейкай новай функцыянальнасцю. Калі мы хочам дадаць у ClickHouse нейкую магчымасць, мы абавязаны павялічыць гэты лік. Гэта значыць, у версіі 20.4 ClickHouse стане працаваць яшчэ лепш. Трэцяя лічба - 20.3.4. Тут 4 - гэта колькасць патч-рэлізаў, у якіх мы новых магчымасцяў не дадавалі, але выпраўлялі нейкія багі. І 4 значыць, што мы зрабілі гэта чатыры разы.

Не варта думаць, быццам гэта нешта жахлівае. Звычайна карыстальнік можа ўсталяваць самую свежую версію, і яна будзе працаваць без якіх-небудзь праблем з аптаймам у год. Але ўявіце, што ў якой-небудзь функцыі для апрацоўкі бітмапаў, якая была дададзена нашымі кітайскімі таварышамі, пры перадачы няправільных аргументаў сервер падае. Мы павінны гэта выправіць. Мы выпусцім новую патч-версію, і ClickHouse стане стабільней.

Калі ў вас ClickHouse працуе ў прадакшне, і выходзіць новая версія ClickHouse з дадатковымі фічамі - напрыклад, 20.4.1 - самая першая, не спяшаецеся ставіць яе ў прадакшн ў першы ж дзень. Навошта яна ўвогуле патрэбная? Калі вы яшчэ не выкарыстоўваеце ClickHouse, тыя вы можаце яе ўсталяваць, і, хутчэй за ўсё, усё будзе добра. Але калі ClickHouse ужо стабільна працуе, то сочыце за патчамі і абнаўленнямі - якія праблемы мы выпраўляем.

Кірыл Швакаў: Хачу дапоўніць крыху пра тэставыя асяроддзі. Усе вельмі баяцца тэставых асяроддзяў і чамусьці лічаць, што, калі ў вас вельмі вялікі кластар ClickHouse, то і тэставае асяроддзе павінна быць не менш ці хаця б у дзесяць разоў менш. Гэта зусім ня так.

Магу сказаць на сваім прыкладзе. У мяне есць праект, і там ёсць ClickHouse. Наша тэставае асяроддзе менавіта для яго - гэта маленькая віртуалка ў Hetzner за дваццаць еўра, дзе абсалютна ўсё разгорнута. Каб гэта рабіць, у нас ёсць поўная аўтаматызацыя ў Ansible, і таму ў прынцыпе няма розніцы, куды каціць - на жалезныя серверы ці проста разгарнуцца ў віртуалка.

Што можна зрабіць? Было б нядрэнна зрабіць у дакументацыі ClickHouse прыклад, як разгарнуць у сябе невялікі кластар – у Docker, у LXC, магчыма, стварыць Ansible playbook, таму што ў розных людзей розныя дэплоі. Гэта шмат што спросціць. Калі ты бярэш і за пяць хвілін разгортваеш кластар, значна прасцей спрабаваць у нечым разабрацца. Так значна зручней, таму што каціць у прад версію, якую ты не праверыў - гэта шлях у нікуды. Часам гэта працуе, а часам не. І таму спадзявацца на поспех - дрэнна.

Максім Кацякоў, senior backend engineer Авіта: Трохі дапоўню аб тэставых асяроддзях з серыі праблем вялікіх кампаній. У нас ёсць паўнавартасны прыёмачны кластар ClickHouse, па схемах дадзеных і налад дакладная копія таго, што ёсць у прадакшне. Гэты кластар разгорнуты ў дастаткова жухлых кантэйнерах з мінімумам рэсурсаў. Мы пішам туды некаторы адсотак ад прадакшн-дадзеных, балазе ёсць магчымасць адрэплікаваць у Кафцы струмень. Там усё сінхранізавана і адскейлена - і па магутнасцях, і па патоку, і, у тэорыі, пры іншых роўных павінна па метрыках паводзіць сябе як прадакшн. Усё патэнцыйна выбухованебяспечнае спачатку коціцца на гэты стэнд і некалькі дзён там настойваецца да гатоўнасці. Але натуральна, гэтае рашэнне дарагое, цяжкае і з ненулявымі выдаткамі на падтрымку.

Аляксей Мілавідаў: Раскажу, што ўяўляе сабой тэставае асяроддзе нашых сяброў з "Яндэкс.Метрыкі". Адзін кластар быў на 600 з нечым сервераў, іншы на 360, і ёсць яшчэ трэці і некалькі кластараў. Тэставое асяроддзе для аднаго з іх - гэта проста два шарды з двума рэплікамі ў кожным. Чаму два шарды? Каб быў не адзін. І рэплікі таксама каб былі. Проста некаторая мінімальная колькасць, якую можна сабе дазволіць.

Гэтае тэставае асяроддзе дазваляе праверыць працаздольнасць запытаў і не зламалася ці нешта па-буйному. Але часта праблемы ўзнікаюць зусім іншага характару, калі ўсё працуе, але ёсць некаторыя невялікія змены з нагрузкай.

Прывяду прыклад. Вырашылі ўсталяваць новую версію ClickHouse. Яна выкладзена на тэставае асяроддзе, пройдзены аўтаматызаваныя тэсты ў самой «Яндэкс.Метрыцы», якія параўноўваюць дадзеныя на старой версіі і на новай, праганяючы ўвесь канвеер. І натуральна, зялёныя выпрабаванні нашага CI. Інакш мы нават не прапанавалі б гэтую версію.

Ўсё выдатна. Пачынаем каціць у прадакшн. Мне прыходзіць паведамленне, што на графіках нагрузка вырасла ў некалькі разоў. Мы адкочваем версію. Я гляджу на графік і бачу: нагрузка сапраўды вырасла ў некалькі разоў падчас выкаткі, і зваротна паменшылася, калі выкацілі. Потым мы сталі адкочваць вэрсію. І нагрузка сапраўды гэтак жа павялічылася і сапраўды гэтак жа зваротна звалілася. Так што выснова такая - нагрузка вырасла ў сувязі з выкладкай, нічога дзіўнага.

Далей было складана пераканаць калег усё ж такі ўсталяваць новую версію. Я кажу: «Усё нармальна, выкочвайце. Трымайце кулачкі, усё будзе працаваць. Цяпер нагрузка вырасла на графіках, але ўсё нармальна. Трымайцеся». Увогуле, мы так зрабілі, і ўсё - версія выкладзеная на прадашкн. Але ці ледзь не пры кожнай выкладцы ўзнікаюць падобныя праблемы.

Kill query павінен забіваць запыты, але ен гэтага не робіць. Чаму?

Да мяне прыйшоў карыстач, нейкі аналітык, і стварыў нейкі запыт, які паклаў мой кластар ClickHouse. Нейкую ноду або кластар цалкам - у залежнасці ад таго, у якую рэпліку або шард запыт патрапіў. Я бачу, што ўсе рэсурсы па CPU на гэтым сэрвэры ў паліцу, усё чырвонае. Пры гэтым сам ClickHouse на запыты адказвае. І я пішу: "Пакажы мне, калі ласка, process list, які запыт спарадзіў гэта вар'яцтва".

Я знаходжу гэты запыт і пішу яму kill. І бачу, што нічога не адбываецца. Мой сервер у палку, ClickHouse далей аддае мне нейкія каманды, паказвае, што сервер жывы, і ўсё выдатна. Але ў мяне дэградацыя ва ўсіх карыстацкіх запытах, пачынаецца дэградацыя па запісе ў ClickHouse, і мой kill query не адпрацоўвае. Чаму? Я думаў, што kill query мусіць забіваць запыты, а гэтага не адбываецца.

Цяпер будзе даволі дзіўны адказ. Справа ў тым, што kill query не забівае запыты.

Kill query выстаўляе маленькі сцяжок пад назвай "я хачу, каб гэты запыт быў забіты". А сам запыт пры апрацоўцы кожнага блока глядзіць на гэты сцяжок. Калі ён выстаўлены, запыт перастае працаваць. Атрымліваецца, што ніхто запыт не забівае, ён сам мусіць усё праверыць і спыніцца. І гэта павінна працаваць ва ўсіх выпадках, калі запыт знаходзіцца ў стане апрацоўкі блокаў даных. Ён апрацуе наступны блок звестак, праверыць сцяжок і спыніцца.

Гэта не працуе ў выпадках, калі запыт заблакаваны на нейкай аперацыі. Праўда, хутчэй за ўсё, гэта не ваш выпадак, таму што, паводле вашых слоў, ён выкарыстоўвае кучу рэсурсаў сервера. Магчыма, што гэта не працуе ў выпадку вонкавага сартавання і яшчэ ў некаторых дэталях. Але ў цэлым такога быць не павінна, гэта баг. І адзінае, што магу параіць, - абнаўляць ClickHouse.

Як разлічыць час адказу пры чытаючай нагрузцы?

Ёсць табліца, у якой захоўваюцца агрэгаты па item - розныя лічыльнікі. Колькасць радкоў - прыкладна сто мільёнаў. Ці можна разлічваць на прадказальны час адказу, калі наліць 1K RPS па 1K item'аў?

Мяркуючы па кантэксце, гаворка ідзе пра чытальную нагрузку, таму што на запіс праблем ніякіх - хоць тысячу, хоць сто тысяч, а часам і некалькі мільёнаў радкоў можна ўстаўляць.

Якія чытаюць запыты бываюць самыя розныя. У select 1 ClickHouse можа выконваць каля дзясяткаў тысяч запытаў у секунду, таму нават запыты па адным ключы ўжо запатрабуюць некаторых рэсурсаў. І такія кропкавыя запыты будуць складаней, чым у якіх-небудзь key-value базах дадзеных, таму што на кожнае чытанне неабходна прачытаць блок даных па індэксе. Індэкс у нас адрасуе не кожны запіс, а кожны дыяпазон. Гэта значыць прыйдзецца пачытаць увесь дыяпазон - гэта 8192 радкі па змаўчанні. І давядзецца расціснуць сціснуты блок дадзеных з 64 Кб да 1 Мб. Звычайна такія кропкавыя запыты займаюць ад некалькіх мілісекунд. Але гэта найпросты варыянт.

Давайце паспрабуем зрабіць простую арыфметыку. Калі памножыць некалькі мілісекунд на тысячу, атрымаецца некалькі секунд. Як быццам трымаць тысячу запытаў па секунду нельга, але насамрэч можна, таму што ў нас некалькі працэсарных ядраў. Так што ў прынцыпе 1000 RPS ClickHouse часам можа трымаць, але на кароткіх запытах, менавіта кропкавых.

Калі трэба маштабаваць кластар ClickHouse па колькасці простых запытаў, то я рэкамендую самае простае - павялічыць колькасць рэплік і адпраўляць запыты на выпадковую рэпліку. Калі адна рэпліка ў вас трымае пяцьсот запытаў у секунду, што цалкам рэальна, то тры рэплікі будуць трымаць паўтары тысячы.

Часам, вядома, можна і ClickHouse наладзіць на максімальную колькасць кропкавых чытанняў. Што для гэтага патрэбна? Першае - паменшыць грануляванасць індэкса. Пры гэтым памяншаць яе варта не да адзінкі, а з разліку, што колькасць запісаў у індэксе будзе некалькі мільёнаў ці дзясяткаў мільёнаў на сервер. Калі ў табліцы сто мільёнаў радкоў, то ў якасці грануляванасці можна выставіць 64.

Можна паменшыць памер сціснутага блока. Для гэтага ёсць наладкі min compress block size, max compress block size. Іх можна зменшыць, пераналіць дадзеныя, і тады кропкавыя запыты будуць хутчэй. Але ўсё роўна ClickHouse – гэта не key-value база дадзеных. Вялікая колькасць маленькіх запытаў - гэта антыпатэрн нагрузкі.

Кірыл Швакаў: Дам параду на выпадак, калі там звычайныя экаўнтэры. Гэта дастаткова стандартная сітуацыя, калі ў ClickHouse захоўваюць нейкі лічыльнік. У мяне ёсць карыстальнік, ён з нейкай краіны, яшчэ нейкае трэцяе поле, і трэба інкрыментна нешта павялічваць. Бераце MySQL, робіце ўнікальны ключ - у MySQL ён duplicate key, а ў PostgreSQL ён conflict - і плюсікам дадаеце. Гэта будзе працаваць моцна лепей.

Калі ў вас крыху дадзеных, сэнсу выкарыстоўваць ClickHouse асабліва няма. Ёсць звычайныя базы даных, і яны добра з гэтым спраўляюцца.

Што падцюніць ў ClickHouse, каб больш дадзеных было ў кэшы?

Прадстаўляльны сітуацыю – на серверах маецца 256 Гб АЗП, у штодзённай руціне ClickHouse бярэ прыкладна 60-80 Гб, у піку – да 130. Што можна ўключыць і падцюніць, каб больш дадзеных было ў кэшы і, адпаведна, было менш паходаў на дыск?

Як правіла, page cache аперацыйнай сістэмы добра спраўляецца з гэтай задачай. Калі вы адкрываеце проста топ, гледзіце там cached ці free - там таксама напісана, колькі закэшавана - то можна заўважыць, што ўся вольная памяць выкарыстаная пад кэш. І гэтыя дадзеныя пры чытанні будуць чытацца не з кружэлкі, а з аператыўкі. Пры гэтым я магу сказаць, што кэш выкарыстоўваецца эфектыўна, таму што кэшуюцца менавіта сціснутыя дадзеныя.

Тым не менш, калі вы хочаце паскорыць некаторыя простыя запыты яшчэ больш, ёсць магчымасць уключыць ўнутры ClickHouse кэш у расціснутых дадзеных. Гэта называецца uncompressed cache. У канфігурацыйным файле config.xml выстаўляеце uncompressed cache size у патрэбнае вам значэнне - я раю не больш за палову вольнай аператыўкі, таму што астатняе сыдзе пад page cache.

Акрамя таго, ёсць дзве наладкі ўзроўню запыту. Першая настройка use uncompressed cache - Уключае яго выкарыстанне. Яе рэкамендуецца ўключаць для ўсіх запытаў, акрамя цяжкіх, якія могуць усе ўвогуле дадзеныя прачытаць і гэты кэш вымыць. І другая налада - гэта нешта накшталт максімальнай колькасці радкоў для выкарыстання кэша. Яна аўтаматычна абмяжоўвае вялікія запыты, каб яны былі міма кэша.

Як можна наладзіць storage_configuration для захоўвання ў аператыўцы?

У новай дакументацыі ClickHouse я вычытаў падзел, злучаны з data storage. У апісанні ёсць прыклад з fast SSD.

Цікава, як можна сканфігураваць тое ж самае з volume hot memory. І яшчэ адно пытанне. Як працуе select з такой арганізацыяй дадзеных, ці будзе ён счытваць увесь набор ці толькі той, што ляжыць на дыску, і ці сціскаюцца гэтыя дадзеныя ў памяці? І як адпрацоўвае секцыя prewhere на такой арганізацыі даных?

Гэтая настройка ўплывае на захоўванне кавалкаў дадзеных, і іх фармат ніяк не мяняецца.
Давайце разгледзім падрабязней.

Наладзіць захоўванне дадзеных у аператыўцы можна. Усё, што канфігуруецца для дыска - гэта яго шлях. Вы ствараеце tmpfs раздзел, які падмантаваны па нейкім шляху ў файлавай сістэме. Паказваеце гэты шлях у якасці шляху для захоўвання дадзеных для самай гарачай часткі, туды пачынаюць паступаць і запісвацца кавалкі дадзеных, усё добра.

Але я не рэкамендую так рабіць з-за нізкай надзейнасці, хаця, калі ў вас мінімум тры рэплікі ў розных дата-цэнтрах, то можна. Калі што, дадзеныя будуць адноўлены. Уявім, што сервер раптам выключылі і ўключылі зваротна. Раздзел падмантаваўся зноў, але там пустата. ClickHouse сервер пры старце бачыць, што ў яго гэтыя кавалкі адсутнічаюць, хоць, паводле метададзеным ZooKeeper яны павінны быць. Ён глядзіць, на якіх рэпліках яны ёсць, запытвае іх і спампоўвае. Такім чынам дадзеныя будуць адноўлены.

У гэтым сэнсе захоўванне дадзеных у аператыўцы прынцыпова не адрозніваецца ад іх захоўвання на дыску, таму што пры запісе дадзеных на дыск яны таксама спачатку трапляюць у page cache і фізічна запісваюцца адкладзена. Гэта залежыць ад варыянту мантавання файлавай сістэмы. Але на ўсялякі выпадак скажу, што ClickHouse не робіць fsync пры insert.

Пры гэтым дадзеныя ў аператыўцы захоўваюцца ў сапраўды такім жа фармаце, што і на дыску. Запыт select сапраўды гэтак жа выбірае кавалкі, якія неабходна чытаць, у кавалках выбірае неабходныя дыяпазоны дадзеных, і чытае іх. І prewhere працуе абсалютна гэтак жа, незалежна ад таго, былі дадзеныя ў аператыўцы ці на дыску.

Да якой колькасці ўнікальных значэнняў эфектыўны Low Cardinality?

Low Cardinality хітра уладкованы. Ён складае слоўнікі даных, але яны лакальныя. Па-першае, слоўнікі свае для кожнага кавалка, па-другое, нават усярэдзіне аднаго кавалка яны могуць быць рознымі для кожнага дыяпазону. Калі колькасць унікальных значэнняў дасягае парогавай колькасці - па-мойму, адзін мільён - слоўнік проста адкладаецца, і ствараецца новы.

Адказ у цэлым: для кожнага лакальнага дыяпазону - скажам, для кожнага дня - дзесьці да мільёна унікальных значэнняў Low Cardinality эфектыўны. Пасля будзе проста fallback, пры якім будзе выкарыстоўвацца шмат розных слоўнікаў, а не адзін. Працаваць яно будзе прыкладна гэтак жа, як звычайны слупок тыпу string, можа быць, некалькі меней эфектыўна, але сур'ёзнай дэградацыі прадукцыйнасці не здарыцца.

Якія лепшыя практыкі па паўнатэкставым пошуку па табліцы з пяццю мільярдамі радкоў?

Ёсць розныя варыянты адказу. Першы - сказаць, што ClickHouse - гэта не сістэма для паўнатэкставага пошуку. Для гэтага ёсць спецыяльныя сістэмы напрыклад, Elasticsearch и Сфінкс. Тым не менш, я ўсё часцей сустракаю людзей, якія гавораць, што пераходзяць з Elasticsearch на ClickHouse.

Чаму такое адбываецца? Яны тлумачаць гэта тым, што Elasticsearch перастае на некаторых аб'ёмах спраўляцца з нагрузкай, пачынаючы з таго, што да пабудовы індэксаў. Індэксы становяцца занадта грувасткімі, і, калі проста перакласці дадзеныя ў ClickHouse, атрымаецца, што яны захоўваюцца ў некалькі разоў больш эфектыўна па аб'ёме. Пры гэтым пошукавыя запыты часта былі не такія, што трэба знайсці ва ўсім аб'ёме даных нейкую фразу з улікам марфалогіі, а зусім іншыя. Напрыклад, знайсці за апошнія некалькі гадзін у логах па нейкай падпаслядоўнасці байт.

У гэтым выпадку вы ў ClickHouse ствараеце азначнік, першым полем у якім будзе дата са часам. І самае вялікае адсячэнне дадзеных будзе менавіта па дыяпазоне дат. Унутры абранага дыяпазону дат ужо, як правіла, можна ажыццявіць паўнатэкставы пошук нават брутфорс-метадам з дапамогай like. Аператар like у ClickHouse - гэта самы эфектыўны аператар like, які вы можаце знайсці. Калі знойдзеце лепш - скажыце мне.

Але ўсё роўна like гэта full scan. І full scan можа быць павольным не толькі па CPU, але і па дыску. Калі раптам у вас адзін тэрабайт дадзеных у суткі, і вы за суткі шукаеце нейкае слова, то давядзецца адсканаваць тэрабайт. А ён напэўна на звычайных цвёрдых кружэлках, і ў выніку яны будуць загружаныя так, што вы на гэты сервер па SSH не зойдзеце.

У гэтым выпадку я гатовы прапанаваць яшчэ адзін маленькі трук. Ён з разраду эксперыментальных - можа спрацуе, а можа не. У ClickHouse ёсць паўнатэкставыя індэксы ў выглядзе трехграммных Блюм-фільтраў. Нашы калегі з кампаніі Arenadata ужо апрабавалі гэтыя індэксы, і часта яны працуюць менавіта так, як прызначана.

Для таго каб правільна іх выкарыстоўваць, варта добра разумець, як менавіта яны працуюць: што з сябе ўяўляе трехграммный Блюм-фільтр і як абраць яго памер. Магу сказаць, што яны дапамогуць для запытаў па нейкіх рэдкіх фразах, падрадкоў, якія рэдка сустракаюцца ў дадзеных. У гэтым выпадку па індэксах будуць абраныя паддыяпазоны, і будзе прачытана менш дадзеных.

Нядаўна ў ClickHouse з'явіліся яшчэ больш прасунутыя функцыі для паўнатэкставага пошуку. Гэта, па-першае, пошук адразу кучы падрадкоў за адзін праход, у тым ліку варыянты з улікам рэгістра, без уліку рэгістра, з падтрымкай UTF-8 ці толькі для ASCII. Выбірайце самы эфектыўны, які вам патрэбен.

Зьявіўся таксама пошук некалькіх рэгулярных выразаў за адзін праход. Вам не трэба пісаць X like адна падрадок or X like іншая падрадок. Адразу пішаце, і ўсё выконваецца максімальна эфэктыўна.

Трэцяе - зараз ёсць набліжаны пошук рэгэкспаў і набліжаны пошук падрадкоў. Калі нехта напісаў слова з памылкай друку, яно будзе шукацца па максімальнай адпаведнасці.

Як лепш арганізаваць доступ у ClickHouse для вялікай колькасці карыстальнікаў?

Раскажыце, як лепш арганізаваць доступ для вялікай колькасці спажыўцоў і аналітыкаў. Як сфарміраваць чаргу, прыарытызаваць запыты max concurrent queries, і якімі прыладамі?

Калі кластар дастаткова вялікі, то добрым рашэннем будзе падняць яшчэ два сервера, якія стануць кропкай уваходу для аналітыкаў. Гэта значыць не пускаць аналітыкаў на пэўныя шарды кластара, а проста стварыць два пустых сервера, без дадзеных, і на іх ужо наладзіць правы доступу. Пры гэтым настройкі карыстальнікаў пры размеркаваных запытах перадаюцца на выдаленыя серверы. Гэта значыць, вы наладжваеце ўсё на гэтых двух серверах, і налады маюць эфект на ўсім кластары.

У прынцыпе гэтыя серверы без дадзеных, але аб'ём аператыўкі на іх вельмі важны для выканання запытаў. Дыск таксама можа выкарыстоўвацца для часовых дадзеных, калі ўключаная вонкавая агрэгацыя ці вонкавае сартаванне.

Важна паглядзець на наладкі, якія звязаны з усімі магчымымі лімітамі. Калі я зараз зайду на кластар «Яндэкс.Метрыкі» як аналітык і задам запыт select count from hits, то мне адразу ж выдадуць выключэнне, што выканаць запыт я не магу. Максімальная колькасць радкоў, якую мне дазволена сканаваць, - гэта сто мільярдаў, а ўсяго на кластары іх пяцьдзесят трыльёнаў у адной табліцы. Гэта першае абмежаванне.

Дапусцім, я прыбяру абмежаванне па колькасці радкоў, і выканаю запыт паўторна. Тады я ўбачу наступнае выключэнне - уключаная налада force index by date. Я не магу выканаць запыт, калі я не ўказаў дыяпазон дат. Ня трэба разлічваць на тое, што аналітыкі будуць паказваць яго ўручную. Тыповы выпадак - напісаны дыяпазон дат where event date between тыдзень. А потым проста не там паказалі дужку, і замест and атрымаўся or - or URL match. Калі абмежаванні няма, яно пайдзе сканаваць слупок URL і выдаткуе проста тону рэсурсаў.

Акрамя таго, у ClickHouse ёсць дзве наладкі прыярытэтаў. Нажаль, яны вельмі прымітыўныя. Адна называецца проста прыярытэт. Калі priority ≠ 0, і выконваюцца запыты з нейкім прыярытэтам, але пры гэтым выконваецца запыт з прыярытэтам, які мае значэнне менш, што значыць больш высокі прыярытэт, то запыт са значэннем прыярытэту большы, што абазначае ніжэйшы прыярытэт, проста прыпыняецца і не будзе працаваць увогуле за гэты час.

Гэта вельмі грубіянская налада, і яна не падыходзіць для тых выпадкаў, калі на кластары ёсць сталая нагрузка. Але калі ў вас кароткія, імпульсныя запыты важныя, а ў асноўным кластар прастойвае, такая настройка падыдзе.

Наступная настройка прыярытэтаў называецца OS thread priority. Яна проста выстаўляе для ўсіх струменяў выканання запыту велічыню nice для шэдулера Linux. Працуе яна так сабе, але ўсё ж працуе. Калі выставіць самае мінімальнае значэнне nice – яно самае вялікае па велічыні, і значыць самы нізкі прыярытэт – а ў запытаў з высокім прыярытэтам выставіць -19, то CPU будзе спажываць нізкапрыярытэтныя запыты прыкладна ў чатыры разы менш, чым высокапрыярытэтныя.

Яшчэ трэба наладзіць максімальны час выканання запыту - скажам, пяць хвілін. Мінімальную хуткасць выканання запыту - гэта самае крутое. Гэтая настройка ёсць даўно, і яна патрабуецца, каб не проста сцвярджаць, што ClickHouse не тармозіць, а каб гэта фарсіраваць.

Уявіце, вы настройваеце: калі нейкі запыт апрацоўвае менш за адзін мільён радкоў у секунду — так рабіць нельга. Гэта ганьбіць наша добрае імя, нашу добрую базу даных. Давайце гэта проста забаронім. Там насамрэч дзве наладкі. Адна называецца min execution speed у радках у секунду, а другая завецца timeout before checking min execution speed па змаўчанні пятнаццаць секунд. Гэта значыць пятнаццаць секунд можна, а потым, калі павольна, то проста кінуць выключэнне - перапыніць запыт.

Яшчэ трэба наладзіць квоты. У ClickHouse ёсць убудаваная магчымасць квот, якая лічыць спажыванне рэсурсаў. Але, нажаль, не жалезных рэсурсаў тыпу CPU, кружэлак, а лагічных - колькасць апрацаваных запытаў, радкоў і прачытаных байт. І можна наладзіць, напрыклад, максімум сто запытаў на працягу пяці хвілін і тысячу запытаў за гадзіну.

Чаму гэта важна? Бо частка запытаў аналітыкі будуць выконваць уручную прама з ClickHouse кліента. І ўсё будзе добра. Але калі ў вас у кампаніі прасунутыя аналітыкі, яны напішуць скрыпт, а ў скрыпце можа быць памылка. І гэтая памылка прывядзе да таго, што запыт выканаецца ў бясконцым цыкле. Ад гэтага і трэба абараніцца.

Ці можна аддаць вынікі аднаго запыту дзесяці кліентам?

У нас ёсць некалькі карыстальнікаў, якія любяць прыходзіць з вельмі вялікімі запытамі ў адзін і той жа момант часу. Запыт вялікі, выконваецца ў прынцыпе хутка, але з-за таго, што такіх запытаў адначасова шмат, становіцца вельмі балюча. Ці можна адзін і той жа запыт, які прыляцеў дзесяць разоў запар, выканаць адзін раз, а вынік яго аддаць дзесяці кліентам?

Праблема ў тым, што менавіта вынікаў кэша ці кэша прамежкавых дадзеных у нас няма. Ёсць page cache аперацыйнай сістэмы, які дазволіць не чытаць дадзеныя з дыска паўторна, але, нажаль, дадзеныя ўсё роўна будуць расціскацца, дэсерыялізоўвацца і апрацоўвацца паўторна.

Хацелася б нейкім чынам гэтага пазбегнуць, альбо кэшуючы прамежкавыя дадзеныя, альбо выбудаваўшы падобныя запыты ў нейкую чаргу і дадаўшы кэш вынікаў. Цяпер у нас ёсць у распрацоўцы адзін pull request, які дадае кэш запытаў, але толькі для подзапросов у секцыі in і join – гэта значыць рашэнне непаўнавартаснае.

Тым не менш, у нас таксама ўзнікае такая сітуацыя. Асабліва кананічны прыклад - гэта запыты з пагінацыяй. Ёсць справаздача, у ёй ёсць некалькі старонак, і ідзе запыт limit 10. Потым тое ж самае, але limit 10,10. Потым яшчэ наступная старонка. І пытаецца, навошта мы кожны раз гэта ўсё лічым? Але зараз рашэння няма, і пазбегнуць гэтага ніяк нельга.

Ёсць альтэрнатыўнае рашэнне, якое ставіцца сайдкарам побач з ClickHouse. ClickHouse Proxy.

Кірыл Швакаў: У ClickHouse Proxy ёсць убудаваны рэйт лімітар і ўбудаваны кэш вынікаў. Тамака зроблена вельмі шмат налад, таму што вырашалася падобная задача. Proxy дазваляе лімітаваць запыты, выбудоўваючы іх у чаргу, і настройваць, колькі па часе жыве кэш запытаў. Калі запыты былі сапраўды аднолькавыя, Proxy аддасць іх шмат разоў, а сыходзіць у ClickHouse за ўсё аднойчы.

У Nginx таксама ёсць кэш у бясплатнай версіі, і гэта таксама будзе працаваць. У Nginx нават ёсць налады, што, калі запыты прыйшлі адначасова, ён будзе тармазіць іншыя, пакуль адзін не выканаецца. Але менавіта ў ClickHouse Proxy настройка зроблена значна лепш. Ён рабіўся менавіта пад ClickHouse, менавіта пад гэтыя запыты, таму больш падыходзіць. Ну і ставіцца проста.

Як быць з асінхроннымі аперацыямі і матэрыялізаванымі ўяўленнямі?

Ёсць такая праблема, што аперацыі з реплейсінг-рухавічком асінхронныя – спачатку запісваюцца дадзеныя, потым адбываецца іх схлопванне. Калі пад таблічкай жыве матэрыялізаваная таблічка з нейкімі агрэгатамі, то дублі ў яе запішуцца. І калі няма нейкай складанай логікі, то даныя будуць задубліраваны. Што можна з гэтым зрабіць?

Ёсць відавочнае рашэнне - рэалізаваць трыгер на пэўны клас маці пры асінхроннай аперацыі схлопывания. Ці ёсць якія-небудзь "сярэбраныя кулі", планы па рэалізацыі падобных функцыянальнасцяў?

Варта разабрацца з тым, як працуе дэдуплікацыя. Тое, пра што я зараз раскажу, не адносіцца да пытання, але на ўсялякі выпадак варта пра гэта ўспомніць.

Пры ўстаўцы ў рэплікаваную табліцу ёсць дэдуплікацыя цалкам устаўленых блокаў. Калі вы паўторна ўставілі адзін і той жа блок, які змяшчае такую ​​ж колькасць тых жа самых радкоў у тым жа самым парадку, то дадзеныя дэдуплікуюцца. Вы атрымаеце “Ok” у адказ на insert, але фактычна будзе запісаны адзін пачак дадзеных, і ён прадубляваны не будзе.

Гэта патрэбна для пэўнасці. Калі падчас устаўкі вы атрымалі "Ok", значыць вашыя дадзеныя ўстаўленыя. Калі вы атрымалі памылку ад ClickHouse, значыць яны не ўстаўлены, і трэба ўстаўку паўтарыць. Але калі падчас устаўкі разарвалася злучэнне, тыя вы не ведаеце, устаўленыя дадзеныя ці не. Адзіны варыянт - гэта паўтарыць устаўку зноў. Калі дадзеныя насамрэч былі ўстаўленыя, і вы іх уставілі паўторна, ёсць дэдэпублікацыя блокаў. Яна патрэбна, каб пазбегнуць дублікатаў.

І важна яшчэ, як яна працуе для матэрыялізаваных уяўленняў. Калі дадзеныя былі дэдуплікаваны пры ўстаўцы ў асноўную табліцу, то ў матэрыялізаваны паказ яны таксама не пойдуць.

Цяпер наконт пытання. У вас больш складаная сітуацыя, таму што вы запісваеце дублікаты асобных радкоў. Гэта значыць не пачак цалкам задубляваная, а менавіта пэўныя радкі, і яны ў фоне схлопваюцца. Сапраўды, дадзеныя будуць схлопываться ў асноўнай табліцы, а ў матэрыялізаванае ўяўленне пойдуць не схлопнутые, і пры мерджах нічога з матэрыялізаванымі ўяўленнямі не адбудзецца. Таму што матэрыялізаванае ўяўленне - гэта не што іншае як трыгер на insert. Пры іншых аперацыях нічога дадаткова з ім не адбываецца.

І я тут парадаваць ніяк не магу. Трэба толькі шукаць канкрэтнае рашэньне для гэтага выпадку. Напрыклад, ці можна ў матэрыялізаваным уяўленні таксама зрабіць яго рэплейсінг, і спосаб дэдуплікацыі, можа быць, будзе гэтак жа працаваць. Але нажаль, не заўсёды. Калі яно агрэгуючае, то не атрымаецца.

Кірыл Швакаў: У нас таксама кастылебудаванне ў свой час яшчэ тое было. Была праблема, што ёсць паказы рэкламы, і ёсць некаторыя дадзеныя, якія мы можам паказваць у рэалтайме - гэта проста паказы. Яны рэдка калі дублююцца, але, калі такое адбываецца, мы іх потым усё роўна схлопнем. І былі рэчы, якія дубляваць нельга - зграі і ўся гэтая гісторыя. Але паказваць таксама іх хацелася практычна адразу.

Як былі зроблены матэрыялізаваныя ўяўленні? Былі ўяўленні, куды пішацца напрамую - ідзе запіс у сырыя дадзеныя, і пішацца ў люхты. Там у нейкі момант дадзеныя не вельмі правільныя, яны дублююцца і гэтак далей. І ёсць другая частка табліцы, дзе яны абсалютна гэтак жа выглядаюць, як і матэрыялізаваныя ўяўленні, гэта значыць па структуры яны абсалютна аднолькавыя. Раз у нейкі час мы пералічваем дадзеныя, далічваем дадзеныя без дублікатаў, пішам у тыя табліцы.

Мы хадзілі праз API - у ClickHouse рукамі гэта працаваць не будзе. І API глядзіць: калі ў мяне ёсць дата апошняга дадання ў табліцу, дзе гарантавана ўжо правільныя дадзеныя, палічаныя, і ён робіць запыт да адной табліцы і да іншай табліцы. З адной запыт выбірае да вызначанай колькасці часу, і з іншай дабірае тое, што яшчэ не палічана. І гэта працуе, але не сродкамі аднаго ClickHouse.

Калі ў вас API нейкае ёсць - для аналітыкаў, для карыстальнікаў - то ў прынцыпе, гэта варыянт. Вы заўсёды далічваеце, заўсёды пералічваеце. Гэта можна рабіць раз на суткі ці яшчэ ў нейкі час. Вы самі для сябе выбіраеце дыяпазон, які вам не патрэбен і не крытычны.

У ClickHouse шмат логаў. Як я магу бачыць усё, што адбываецца з серверам, у моманце?

У ClickHouse вельмі вялікая колькасць розных логаў, і гэтая колькасць падвышаецца. У новых версіях нейкія з іх нават па змаўчанні ўключаны, у старых версіях іх трэба ўключаць пры абнаўленні. Тым не менш, іх усё больш і больш. Хацелася б бачыць у канчатковым рахунку, што адбываецца зараз у мяне з серверам, можа быць, на нейкім зводным дашбордзе.

Ці няма ў вас у камандзе ClickHouse, ці ў камандах вашых сяброў, якія падтрымліваюць нейкі функцыянал гатовых дашбордаў, якія б гэтыя логі адлюстроўвалі ў выглядзе ўжо гатовага прадукта? У канчатковым рахунку, проста так логі глядзець у ClickHouse - гэта выдатна. Але вельмі класна, калі б гэта было ўжо ў выглядзе дашборда прыгатавана. Я б ад гэтага кайфануў.

Дашборды ёсць, праўда яны не стандартызаваныя. У нас у кампаніі дзесьці 60 каманд выкарыстоўваюць ClickHouse, і самае дзіўнае, што ў многіх з іх дашборды, якія яны самі сабе зрабілі, і крыху іншыя. Некаторыя каманды выкарыстоўваюць унутраную інсталяцыю «Яндэкс.Аблокі». Там ёсць некаторыя гатовыя справаздачы, хаця і не ўсе неабходныя. У іншых сваё.

У маіх калегаў з "Метрыкі" ёсць свой дашборд у Grafana, а ў мяне ёсць свой па іх жа кластару. Я там гляджу штукі кшталту кэш хіт для кэша засечак. І нават яшчэ складаней тое, што мы выкарыстоўваем розныя прылады. Свой дашборд я ствараў на вельмі старым інструменце, які называецца Graphite-web. Ён зусім непрыгожы. І я так да гэтага часу ім і карыстаюся, хоць Grafana, напэўна, была б зручней і прыгажэй.

Базавая рэч у дашбордах аднолькавая. Гэта сістэмныя метрыкі па кластары: CPU, памяць, дыск, сетка. Іншыя – колькасць адначасовых запытаў, колькасць адначасовых мерджаў, колькасць запытаў у секунду, максімальная колькасць кавалкаў для партыцый табліц MergeTree, лаг рэплікацыі, памер чаргі рэплікацыі, колькасць устаўленых радкоў у секунду, колькасць устаўленых блокаў у секунду. Гэта ўсё, што атрымліваецца не з логаў, а з метрык.

Уладзімір Калабаеў: Аляксей, я хацеў бы крыху скарэктаваць. Ёсць Grafana. У Grafana ёсць datasource, якім з'яўляецца ClickHouse. Гэта значыць, я магу з Grafana рабіць запыты адразу ў ClickHouse. У ClickHouse ёсць табліца з логамі, яна ва ўсіх аднолькавая. Я хачу ў выніку ў Grafana звяртацца да гэтай табліцы логаў і бачыць тыя запыты, якія прыкладае мой сервер. Было б выдатна мець такі дашборд.

Я яго навяласіпедыў сам. Але ў мяне ўзнікае пытанне - калі яно ўсё стандартызаванае, і Grafana выкарыстоўваецца ўсімі запар, чаму ў «Яндэксе» няма такога афіцыйнага дашборда?

Кірыл Швакаў: На самой справе datasource, які да ClickHouse, зараз падтрымлівае Altinity. І я проста хачу даць вектар, куды капаць і каго штурхаць. Можна спытаць з іх, таму што "Яндэкс" усё-ткі робіць ClickHouse, а не гісторыю вакол яго. Altinity – гэта асноўная кампанія, якая зараз прасоўвае ClickHouse. Яны яго не кінуць, а будуць падтрымліваць. Таму што ў прынцыпе, каб загрузіць дашборд на сайт Grafana, трэба толькі зарэгістравацца і заліць яго - праблем асаблівых няма.

Аляксей Мілавідаў: За апошні год у ClickHouse дадалося шмат магчымасцяў па прафіляванні запытаў. Ёсць метрыкі для кожнага запыту па выкарыстанні рэсурсаў. А зусім нядаўна дададзены яшчэ больш нізкаўзроўневы прафайлер запытаў, каб глядзець, дзе запыт праводзіць кожную мілісекунду. Але каб скарыстацца гэтай функцыянальнасцю, мне даводзіцца адкрыць кансольны кліент і набраць запыт, які я ўвесь час забываю. Я яго кудысьці захаваў і ўвесь час забываю, куды менавіта.

Я б хацеў, каб быў інструмент, у якім проста напісана - вось вашыя цяжкія запыты, згрупаваныя па класах запытаў. Націснуў на які-небудзь, і мне б сказалі, што ён цяжкі таму. Цяпер такога рашэння няма. І сапраўды даволі дзіўна, што, калі людзі ў мяне пытаюцца: «Скажыце, ёсць якія-небудзь гатовыя дашборды для Grafana?», я кажу: «Зайдзіце на сайт Grafana, там кам'юніці “Дашборды”, і там ёсць дашборд ад Дзімка, ёсць дашборд ад Касцяна. Што гэта такое, я не ведаю, я сам не карыстаўся».

Як уздзейнічаць на Мерджы, каб сервер не падаў у OOM?

У мяне ёсць табліца, у табліцы ўсяго адна партыцыя, яна ReplacingMergeTree. Я ў яе пішу дадзеныя цягам чатырох гадоў. Мне трэба было зрабіць у яе альтэр і выдаліць сякія-такія дадзеныя.

Я гэта зрабіў, і падчас апрацоўкі гэтага запыту была з'едзена ўся памяць на ўсіх серверах кластара, і ўсе серверы кластара дружна сышлі ў OOM. Потым яны ўсе разам усталі, пачалі выконваць мердж гэтай жа самай аперацыі, гэтага блока дадзеных, і зноў упалі ў OOM. Потым яны зноў усталі і зноў упалі. І гэтая штука не спынялася.

Потым выявілася, што гэта насамрэч баг, які хлопцы пафіксілі. Гэта вельмі выдатна, дзякуй вялікі. Але асадак застаўся. І цяпер, калі я думаю пра тое, што трэба рабіць нейкі мердж у табліцы, у мяне з'яўляецца пытанне - а чаму я не магу ўзяць і на гэтыя мерджы нейкім чынам уздзейнічаць? Напрыклад, абмежаваць іх па колькасці патрабаванай аператыўнай памяці, ці ў прынцыпе па іх колькасці, якая будзе апрацоўваць менавіта гэтую табліцу.

У мяне ёсць табліца, якая называецца «Метрыкі», апрацоўвай мне яе, калі ласка, у два патокі. Не трэба пладзіць дзесяць ці пяць мерджаў паралельна, зрабі ў два. Я думаю, што ў два ў мяне памяці хопіць, а на тое, каб дзесяць апрацоўваць, можа не хапіць. Чаму страх застаецца? Таму што табліца расце, і калі-небудзь я сутыкнуся з сітуацыяй, што ў прынцыпе ўжо не з-за бага, а з-за таго, што дадзеныя будуць мяняцца ў такой вялікай колькасці, што мне проста памяці на серверы не хопіць. І тады сервер будзе падаць у OOM пры мерджы. Прычым мутацыю я магу адмяніць, а мерджы ўжо няма.

Вы ведаеце, пры мерджах сервер не будзе падаць у OOM, таму што пры мерджы выкарыстоўваецца колькасць аператыўкі толькі на адзін маленькі дыяпазон дадзеных. Так што ўсё будзе добра незалежна ад аб'ёму дадзеных.

Уладзімір Калабаеў: Добра. Тут момант такі, што пасля таго, як зрабілі баг фікс, я спампаваў сабе новую версію, і на іншай табліцы, больш маленькай, дзе партыцый шмат, зрабіў падобную аперацыю. І падчас мерджы на серверы было спалена каля 100 Гб аператыўнай памяці. У мяне было 150 занята, 100 з'ела, і засталося акно на 50 Гб, таму я ў OOM не зваліўся.

Што мяне на дадзены момант абараняе ад таго, каб я не падаў у OOM, калі ен сапраўды спажывае па 100 Гб аператыўнай памяці? Як быць у сітуацыі, калі раптам аператыўная памяць на мерджах скончыцца?

Аляксей Мілавідаў: Ёсць такая праблема, што выдатак аператыўнай памяці менавіта на Мерджы не абмяжоўваецца. І другая праблема ў тым, што, калі нейкі мердж быў прызначаны, то яго неабходна выканаць, таму што ён запісаны ў лог рэплікацыі. Лог рэплікацыі - гэта тыя дзеянні, якія патрэбныя, каб прывесці рэпліку ў кансістэнтны стан. Калі не зрабіць ручныя маніпуляцыі, якія гэты лог рэплікацыі адкоціць назад, мердж прыйдзецца, так ці інакш, выканаць.

Вядома, было б не лішнім мець абмежаванне па аператыўцы, якое "на ўсялякі выпадак" абараняе менавіта ад OOM. Яно не дапаможа мерджу выканацца, ён будзе пачынацца зноў, даходзіць да нейкага парога, кідаць выключэнне, а потым зноў пачынацца - нічога добрага з гэтага не выйдзе. Але ў прынцыпе абмежаванне гэта ўвесці было б карысна.

Як будзе адбывацца распрацоўка Golang-драйвера для ClickHouse?

Golang-драйвер, які напісаў Кірыл Швакоў, зараз афіцыйна быццам бы падтрымліваецца камандай ClickHouse. Ён у рэпазітары ClickHouse, ён зараз вялікі і сапраўдны.

Невялікая рэмарка. Ёсць выдатнае і ўсімі каханае сховішча нармалёвых формаў бясконцага парадку – гэта Vertica. У іх таксама ёсць свой афіцыйны python-драйвер, які падтрымліваецца распрацоўшчыкамі Vertica. І некалькі разоў было такое, што версіі сховішчы і версіі драйвера вельмі крута раз'язджаліся, і драйвер у нейкі момант пераставаў працаваць. І другі момант. Падтрымка гэтага афіцыйнага драйвера, здаецца мне, вядзецца сістэме "ніпель" - ты пішаш ім issue, і яно вісіць вечна.

У мяне два пытанні. Цяпер Golang-драйвер Кірыла - гэта амаль дэфолтны спосаб камунікаваць з Golang з ClickHouse. Хіба што нехта праз http інтэрфейс камунікуе да гэтага часу, таму што яму так падабаецца. Як будзе адбывацца тэхналогія гэтага драйвера? Ці будзе яна сінхранізавацца з нейкімі breaking changes у самім сховішчы? І які парадак разгляду issue?

Кірыл Швакаў: Першае - як усё ўладкована бюракратычна. Гэты момант не абмяркоўваўся, таму адказаць мне няма чаго.

Каб адказаць на пытанне пра issue, патрэбная невялікая гісторыя драйвера. Я працаваў у кампаніі, у якой было шмат дадзеных. Гэта была рэкламная круцілка з вялікай колькасцю падзей, якія трэба было недзе захоўваць. І ў нейкі момант з'явіўся ClickHouse. Мы налілі туды дадзеныя, і першыя часы ўсё было добра, а потым ClickHouse упаў. На той момант мы вырашылі, што яно нам не патрэбнае.

Праз год мы вярнуліся да ідэі выкарыстання ClickHouse, і нам трэба было неяк туды пісаць дадзеныя. Уступная была такая - жалеза вельмі слабое, рэсурсаў мала. Але мы заўжды так працавалі, і таму паглядзелі ў бок натыўнага пратаколу.

Бо мы працавалі на Go, было зразумела, што патрэбен драйвер на Go. Я рабіў яго практычна фултайм - гэта была мая працоўная задача. Да нейкага моманту мы яго давялі, і ў прынцыпе ніхто не меркаваў, што нехта акрамя нас будзе яго выкарыстоўваць. Пасля прыйшоў CloudFlare роўна з такой жа праблемай, і ў нейкі час мы з імі працавалі вельмі роўна, таму што ў іх былі адны і тыя ж задачы. Прычым мы гэта рабілі і ў ClickHouse сам, і ў драйверы.

У нейкі момант я проста перастаў ім займацца, таму што мая актыўнасць з пункту гледжання ClickHouse і з працай крыху змянілася. Таму issues не зачыняюцца. Перыядычна ў рэпазітар камічаць людзі, якім самі нешта патрэбна. Тады я гляджу pull request і часам нават нешта сам праўлю, але гэта здараецца рэдка.

Да драйвера жадаецца вярнуцца. Некалькі гадоў таму, калі ўся гэтая справа пачыналася, ClickHouse быў таксама іншы і з іншымі магчымасцямі. Цяпер жа ёсць разуменне, як перарабіць драйвер, каб было добра. Калі гэта адбудзецца, то версія 2 будзе ў любым выпадку несумяшчальная з-за назапашаных мыліц.

Як гэтую справу арганізаваць, я не ведаю. У мяне самога часу не так многа. Калі нейкія людзі будуць дапілоўваць драйвер, я змагу ім дапамагаць і расказваць, што рабіць. Але менавіта актыўны ўдзел "Яндэкса" ў развіцці праекта пакуль ніяк не абмяркоўвалася.

Аляксей Мілавідаў: Насамрэч пакуль няма ніякай бюракратыі з нагоды гэтых драйвераў. Адзінае - яны вынесены ў афіцыйную арганізацыю, гэта значыць гэты драйвер прызнаны афіцыйным рашэннем па змаўчанні для Go. Ёсць нейкія іншыя драйверы, але яны ідуць асобна.

У нас усярэдзіне ніякай распрацоўкі для гэтых драйвераў няма. Пытанне – ці зможам мы наняць асобнага чалавека, не на канкрэтна гэты драйвер, а на развіццё ўсіх кам'юніці-драйвераў, ці зможам знайсці кагосьці звонку.

Вонкавы слоўнік не паднімаецца пасля перазагрузкі з уключанай наладай lazy_load. Што рабіць?

У нас уключаная настройка lazy_load, і пасля перазагрузкі сервера слоўнік сам не паднімаецца. Ён паднімаецца толькі пасля таго, як карыстач звернецца да гэтага слоўніка. І пры першым звароце выдае памылку. Ці можна неяк аўтаматычна сродкамі ClickHouse загружаць слоўнікі, ці трэба самім заўсёды кантраляваць іх гатоўнасць, каб карыстачы не атрымлівалі памылак?

Магчыма ў нас старая версія ClickHouse, таму слоўнік аўтаматычна не загружаўся. Можа, такое?

Па-першае, слоўнікі можна фарсіравана загрузіць з дапамогай запыту system reload dictionaries. Па-другое, наконт памылкі — калі слоўнік ужо загружаны, то запыты будуць працаваць па тых дадзеных, якія былі загружаныя. Калі слоўнік яшчэ не быў загружаны, ён будзе загружацца прама падчас запыту.

Для цяжкіх слоўнікаў гэта не надта зручна. Напрыклад, трэба прыцягнуць мільён радкоў з MySQL. Нехта робіць просты select, але гэты select будзе чакаць той самы мільён радкоў. Тут ёсць два рашэнні. Першае - выключыць lazy_load. Другое - калі сервер паднімаецца, перад тым, як уключыць на яго нагрузку, зрабіць system reload dictionary ці проста выканаць запыт, які выкарыстоўвае слоўнік. Тады слоўнік будзе загружаны. Трэба самім кантраляваць даступнасць слоўнікаў са ўключанай наладай lazy_load, таму што аўтаматам ClickHouse іх не падцягвае.

На апошняе пытанне адказ — ці версія старая, ці трэба адладжваць.

Як быць з тым, што system reload dictionaries не падгружае ніводны з мноства слоўнікаў, калі хоць бы адзін з іх падае з памылкай?

Ёсць яшчэ пытанне наконт system reload dictionaries. У нас два слоўнікі - адзін не прагружаецца, другі прагружаецца. System reload dictionaries у такім разе не падгружае ніводны слоўнік, і прыходзіцца кропкава падгружаць пэўны па ім назову з дапамогай system reload dictionary. Гэта таксама злучана з версіяй ClickHouse?

Жадаю ўзрадаваць. Гэтыя паводзіны мяняліся. Значыць, калі вы абновіце ClickHouse, то яно таксама памяняецца. Калі вас не задавальняе бягучыя паводзіны system reload dictionaries, абнавіцеся, і будзем спадзявацца, што яно зменіцца ў лепшы бок.

Ці ёсць спосаб канфігураваць рэквізіты ў канфігу ClickHouse, але не свяціць іх пры памылках?

Наступнае пытанне пра памылкі, злучаныя са слоўнікам, а менавіта рэквізіты. Мы прапісалі рэквізіты падлучэння ў канфігу ClickHouse да слоўніка, і пры памылцы мы гэтыя рэквізіты і пароль атрымліваем у адказ.

Мы вырашылі гэтую памылку вынясеннем рэквізітаў у канфіг драйвера ODBC. Ці ёсць нейкі спосаб сканфігураваць рэквізіты ў канфігу ClickHouse, але не свяціць гэтыя рэквізіты пры памылках?

Тут рашэнне сапраўды - паказваць гэтыя credentials у odbc.ini, а ў самім ClickHouse паказваць толькі ODBC Data Source Name. Для астатніх крыніц слоўнікаў такога не будзе - ні для слоўніка з MySQL, ні для астатніх вы не павінны бачыць пароль пры паведамленні аб памылцы. Для ODBC я таксама пагляджу - калі такое ёсць, трэба гэта проста прыбраць.

Бонус: фоны для Зума з вячорак.

Па кліку на карцінку для самых упартых чытачоў адкрыюцца бонусныя фоны з вячорак. Тушым пажар разам з маскотамі тэхналогій Авіта, раімся з калегамі з пакоя сісадміна ці олдскульнага кампутарнага клуба і праводзім дэйлі пад мастом на фоне графіці.

ClickHouse для прасунутых карыстальнікаў у пытаннях і адказах

Крыніца: habr.com

Дадаць каментар