Выбираем СУБД для хранения временных рядов

в 13:43, , рубрики: nosql, Анализ и проектирование систем, Блог компании Конференции Олега Бунина (Онтико), временные ряды, высокая производительность, павел филонов, Разработка веб-сайтов, СУБД, метки:

Выбираем СУБД для хранения временных рядов - 1

Павел Филонов (Лаборатория Касперского)

Сегодня будем говорить о хранении временных рядов. Я постараюсь рассказать, какие подходы я применял для того, чтобы попытаться как можно больше своего субъективизма выкинуть, заменить его чем-то более объективным, а субъективный взгляд оставить где-нибудь в самом конце.

Выбираем СУБД для хранения временных рядов - 2

Почти всегда в последнее время в своей практике я замечаю, что придумывать что-то новое для решения задач стандартных уже почти никогда не надо. Почти всегда нужно просто выбрать — как выбрать йогурт в магазине. Вы приходите, там полочка, там эти ряды все заставлены, и нужно решить, какой вам выбрать: привычный, попробовать новый, либо самый вкусный, либо самый полезный. И все они яркие, красивые, с рекламкой. Все один другого лучше.

Великие еще давно говорили о том, что это большая проблема. О том, что эти яркие занавески могут немножко затмить наш выбор.

Как же нам попытаться? Все равно, честно, объективно полностью не получится. Всегда будет субъективизм в выборе, иначе быть не может. Но, может быть, можно как-то этот субъективизм нивелировать? Может быть, зажать в какие-то контролируемые рамки, чтобы что-то из этого получилось?

Сегодня я постараюсь рассказать, какие подходы я применял для того, чтобы попытаться как можно больше своего субъективизма выкинуть, заменить его чем-то более объективным, а субъективный взгляд оставить где-нибудь в самом конце.

Перед этим, правда, я хочу сначала поговорить немножко о задаче, которая стояла. На мой взгляд, понимание реальной задачи, которую в каком-то смысле пощупать можно — оно всегда проясняет ситуацию. Она лучше позволяет понять те либо иные решения, которые были сделаны. Поэтому я начну с Джона МакКлейна.

Выбираем СУБД для хранения временных рядов - 3

Это Джон — мой герой. Кто вот в детстве, когда смотрел, как он бьет террористов, хотел быть таким же, как Джон МакКлейн? Не все, да, я вижу. Вот я очень хотел!

Я смотрел, как он в первой части бил террористов, во второй, в третьей. И мне начало казаться, совсем недавно, что я чем-то похож на него. Тяжело увидеть сходство, я понимаю. Наверное, не внешнее, а чуть-чуть — чем мы начинаем с ним вместе заниматься. В частности, в четвертой части своих похождений он бился уже не просто с террористами, он бился с очень вредными кибер-террористами, которые не просто пытались кого-то захватить и терроризировать, которые пытались взломать газовые станции, пытались сломать линии электроснабжения, которые пытались перестроить светофоры в большом городе. Представляете, что будет, если хаотично перестроить светофоры в Москве? Возможно, ничего не изменится, но есть подозрение, что не стоит этого делать сразу.

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

Проблема возникла чуть позже, после выхода фильма, примерно в 2010 году, когда, похоже, что фильм посмотрели многие. Некоторые даже прониклись. К сожалению, не все, из тех, кто прониклись, люди хорошие. В частности, название, которое звучит посередине — это один из достаточно популярных зловредов, который был обнаружен порядка шести лет назад, у которого было много умений, много назначений.

Выбираем СУБД для хранения временных рядов - 4

Одним из самых неприятных его назначений был взлом систем автоматизированного управления технологическими процессами (АСУТП) и нанесение уже не просто коммерческого вреда путем кражи информации либо стирания чего-либо, а перепрограммирование технологических процессов на нанесение физического вреда. В частности, из-за его действий программа обогащения урана, по-моему, в Иране, была откинута на несколько лет назад. Он просто вывел из строя часть установок по обогащению. Ситуация, к сожалению, повторялась. Несколько случаев были официально зарегистрированы. Были созданы отчеты, которые подтверждали, что эти заводы выходили из строя не сами по себе, а непосредственно в силу испытания некоторых атак, целевых атак на АСУТП.

Эта задача начала приводить к поиску решения. Это проблема, многие считают, что это проблема. В АСУТП не все очень хорошо с безопасностью. Надо туда привносить новые элементы безопасности и стараться защищать эти объекты. Что за объекты? Вот, чтобы какой-то образ был перед глазами, я взял просто какую-то картиночку:

Выбираем СУБД для хранения временных рядов - 5

Какой-то заводик, скорее всего нефтеперегонный, который делает очень важную и полезную вещь. И нам нужно пытаться его защищать от тех угроз, которые могут на него смотреть со стороны кибер-части. Это задача сложная, она очень многослойная, я бы сказал.

На этот заводик можно взглянуть с разных ракурсов. Например, можно смотреть с точки зрения сетевого поведения: рисовать топологию сети, смотреть, кто с кем взаимодействует, кому можно с кем взаимодействовать, кому нельзя. Это один слой решения.

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

Я работаю в отделе, который находится еще на другом слое, который следит за тем, как работает именно сам технологический процесс, как включаются реле, работают конвейеры, нагреваются баки, гоняется жидкость по трубопроводам. И мы, например, смотрим на этот объект примерно вот так.

Выбираем СУБД для хранения временных рядов - 6

Любой технологический процесс, по сути, есть динамическая система, которая во времени меняется. Она многомерная, у нее много характеристик. Здесь я нарисовал пять рядов, для среднего объекта их может быть тысячи, может быть, десятки тысяч. Это просто какой-то искусственный пример, чтобы представить, как будут выглядеть наши данные, глазками.

Конечно, основная задача — это обработка на потоке. Потому что исторические данные по взлому — интересно, но не столь. Но для того, чтобы ее реализовывать, эти данные не только нужно обрабатывать, но и желательно где-то сохранять. Для исторических расследований, для форензика. Например, нам очень важно сохранять большие объемы исторических данных для обучения наших систем онлайн-обработки.

Отсюда начинает возникать уже конкретная техническая задача. Если у нас есть вот такие данные (про модели я расскажу чуть-чуть), и у нас есть их характеристики, с которыми эти данные поступают в систему, как нам наиболее разумно и рационально организовать подсистему хранения, к которой мы будем доступаться, для того чтобы проводить исторический анализ, либо запрашивать для наших конкретных исследований? Так мы приходим уже к проблеме.

Перед проблемой, правда, немножко о схеме данных, чтобы совсем чуть по конкретике вы представляли, о чем идет речь. Уже на таком немножко конкретном языке.

Выбираем СУБД для хранения временных рядов - 7

Вот одна точка в одном ряду характеризуется обычно тремя числами: это ее некий идентификатор (номер канала), 42 — температура, 14 — давление, 13 — включение/выключение реле (возможно). Момент времени, когда что-то изменилось в этой динамической системе, и значение, на которое оно поменялось. Значение может быть вещественно-значное, может быть целочисленное, может быть логическое. Вещественно-значное описывает их все.

Чуть-чуть о характеристиках, чтобы было видно что, наверное, это имеет какое-то отношение к тематике конференции. Там не так все просто с объемами.

К сожалению, для среднестатистического объекта количество таких рядов насчитывает порядка десятков тысяч, в исключительных случаях может быть на порядок больше. С интенсивностью, слава Богу, чуть-чуть получше. Обычно значения сенсоров собираются в среднем раз в секунду. Может быть, чуть чаще, может быть, чуть медленнее, но по реальным объектам характеристики примерно таковы.

И мы начинаем чуть-чуть уже пытаться представлять себе объемы, в которых нам предстоит работать. Это очень важный момент, потому что, по сути, из этих чисел можно начать выводить то, без чего я, например, очень некомфортно себя чувствую — без нефункциональных требований.

Когда иногда говорят: «Сделайте, чтобы было быстро и хорошо», а я не понимаю таких слов. Я начинаю пытать человека: «А что такое «быстро»? А что такое «хорошо»? А какие у вас данные? А сколько у вас объемов? А какие у вас интенсивности?». Только после того, как этот чек-лист пройден, и основные пункты известны, я уже могу начать пытаться хотя бы представлять себе решения.

Выбираем СУБД для хранения временных рядов - 8

Там, правда, тоже не все так просто, там много решений, там совсем оно далеко не одно. Я уверен, что каждый из вас может спокойно сейчас вписать в это список еще пять своих любимых СУБД. Конечно, все здесь просто не поместятся. Они разные. Какие-то хорошо работают в одном случае, какие-то лучше работают в другом случае, какие-то, наверное, хорошо работают именно для той задачи, про которую я рассказывал.

Но какие? Как понять? Как выбрать? Это большая проблема. Я сталкиваюсь с ней часто и постоянно. Придумывать новое уже нужно очень редко, почти всегда нужно просто разумно выбрать как-то из этого набора.

Есть несколько подходов к этому выбору. Первый — я его назвал «неинженерный» подход.

Выбираем СУБД для хранения временных рядов - 9

К сожалению, а может быть, я не знаю, к счастью, он иногда пропагандируется. Какие примеры неинженерного подхода?

  • Например, вот такой — все хранили в Х, давайте и здесь использовать его же. Неважно, что задача другая, предметная область другая — мы знаем, как работает Х.
  • Или вот такой больной способ, когда «Мы там его использовали, не надо этого делать, ни в коем случае, пожалуйста». Я и такие встречал.
  • Третий — мой любимый. Да, я чувствую, многие со мной солидарны. Но опасный, чуть-чуть опасный, но любимый.
  • Мы же на конференции с вами, здесь рассказывают про базы данных. Я, наверное, не помню конференции, где больше рассказывают про базы данных, чем здесь. И конечно, первое что — приходят люди после, на следующий день на работу, говорят: «Нам там про такую штуку рассказали, давайте ее пробовать!».
  • Вот этот мне тоже очень нравится — вышла статья где-то, там все здорово: графики просто экспоненциальные наверх летят, наверху доллар нарисован, все радуются. Давайте выбирать вот это.

Конечно, слайд юмористический, но давайте будем честны — а кто сможет сейчас смело встать, представится и сказать, что «действительно, я такой-то, и я раньше использовал неинженерный подход»?

А можно попросить кого-нибудь из помощников? Пожалуйста, микрофончик.

Представьтесь, пожалуйста, и скажите это. Смелее!

Реплика из зала: Я Владимир Мясников. Мы использовали подход «Давайте возьмем Х, а там уже разберемся».

Спасибо большое, Владимир! Давайте поаплодируем!

Кстати, мы выложили в открытый доступ видеозаписи последних пяти лет конференции разработчиков высоконагруженных систем HighLoad++. Смотрите, изучайте, делитесь и подписывайтесь на канал YouTube.

Это как такая часть терапии. Вы знаете, да? Чтобы бороться с проблемой, надо сначала ее осознать и признаться самим себе. Владимир — явно смелый человек, и многие здесь смелые, они готовы признаться, что это плохой подход. Может быть, есть другой?

Выбираем СУБД для хранения временных рядов - 10

Давайте назовем его «инженерный». Наверное, он чуть посложнее. Может быть, он даже как-то структурирован и декомпозирован. Я попробовал свою декомпозицию, она не претендует на общность. Давайте я по пунктам ее расскажу и, по сути, это будет, заодно, содержание дальнейшей части доклада.

  1. Сначала неплохо все-таки почитать. Что есть, что появилось за последние годы? Потому что я со страхом жду, когда ко мне в «Фидли» приедет статья «10 новых баз данных, которые вы должны выучить за эту неделю». Я чувствую, что рано или поздно это произойдет. Там появляется все с такой скоростью, что трудно успевать следить, и надо знакомиться постоянно с литературой. В том числе, путем того, что вы слушаете на конференции: кто что попробовал, кто чем доволен, кто чем недоволен. И таким образом мы свой опыт распространяем на других людей.
  2. Вообще говоря, было бы неплохо понять, если мы будем выбирать, то по каким критериям — цена, скорость, масштабируемость? С ними нужно определиться. Выбирать по всем критериям невозможно. Скорее всего, нефункциональные требования ваши могут вам подсказать, какие из критериев в данной задаче, и только в данной задаче, вам стоит рассматривать в первую очередь, а какие во вторую.
  3. Вот это самый интересный, такой долгожданный пункт: надо же выбрать, кого сравнивать. Должны быть конкурсанты. К сожалению, сравнивать всех сложно. Должен быть какой-то предварительный отбор. Когда еще до того, как вы дошли до конкретных цифр, вы понимаете, что это, похоже, может подойти как решение, а это — не может. Или вы просто понимаете, что у вас не хватит сил померить все, и тогда нужно выбирать то, что вам кажется наиболее адекватным пока. Но, конечно, из одного пункта список этот вряд ли будет состоять, вряд ли даже из двух.
  4. Про четвертый пункт я буду говорить, наверное, больше всего. Если мы выбрали, что мы меряем, и выбрали даже, кого мы меряем, дальше очень тонкий и очень интересный вопрос: «Как мы это делаем?». Потому что, даже если взять двух людей, и они выберут, что они меряют одно и то же и одних и тех же, они могут это делать совершенно по-разному, и цифры могут получаться очень разные. Поэтому где-то, может быть, я буду уходить в лишние нюансы, но, на мой взгляд, это самая интересная часть: как мерили-то, как воспроизвести это тем либо иным образом. Здесь мы посвятим много времени этому.
  5. Это достаточно тяжелая часть, потому что потом ее надо реализовать. Она сама такая долгая, требует каких-то трудозатрат, работ. Об этом мы еще поговорим. Вообще, провести это тестирование, для каждого из конкурсантов понять, какие циферки ему соответствуют. Это нужно делать руками, даже писать код. Боже мой!
  6. Кстати, результатов подчас недостаточно. Если вы принесете красивую табличку с цифрами «вашим» и скажете: «Вот — результат». Скажут: «Ну, хорошо. И что?» Должен быть анализ. Цифр недостаточно. Всегда за цифрами должны стоять нормальные слова, которые объясняют их, они их раскрывают, пытаются донести все-таки смысл этого результата, а не просто оставить его в виде голых цифр, сказав: «Все и так понятно».
  7. И в конце все-таки требуются уже какие-то конкретные рекомендации. Причем, они вряд ли могут быть совсем строгие, что «только вот это подойдет и все». На самом деле, естественно, решений может быть несколько. Надо говорить, может быть, с какой долей уверенности подойдет то либо иное решение. Например, в виде отчета и конкретных рекомендаций.
  8. Сложный подход. Когда я его записывал, больше трех пунктов — это вообще сложно, а тут их получилось аж целых восемь. Этот подход, я его вижу, но очень нечасто и я понимаю, почему. Он трудозатратен. Действительно, нужно потратить на это время, человеко-часы, если хотите, какое-то усилие, хотя, казалось бы: «Давайте возьмем Х, а там уже дальше разберемся».

Но здесь, если мы тратим время, мы для чего-то это делаем. Где-то мы хотим его сэкономить. Например, я в свое время понял, что тестирование очень экономит время на разборе «багов». Может быть, и здесь мы можем сэкономить время? Это возможно.

Кто сталкивался с ситуацией, когда ему приходилось от релиза к релизу в продакшне менять базу данных? Да вот, мало людей сталкивались. А кому это нравилось? Здесь вообще рук нет. Это очень опасно.

Если выбор сделан был необоснованный и слепой, у вас есть риск не попасть в нужные вам нефункциональные требования. Особенно, если они начнут меняться. У кого они менялись в свое время? Да, такое тоже возможно. Поэтому эти трудозатраты могут быть окуплены, в будущем, конечно. То есть их трудно предсказать, насколько они вам окупят времени но, поверьте, иногда это того стоит.

Вот наш план. Давайте по нему пойдем. Начнем с критического обзора литературы.

Выбираем СУБД для хранения временных рядов - 11

Я в основном расскажу, что мне не понравилось, когда я начал читать. Какие-то конкретные моменты. Например, очень много сравнений баз данных для той либо иной задачи проводят — как вы думаете кто? — сами разработчики этих баз данных.

Я заметил стопроцентную корреляцию, действительно стопроцентную. Если разработчик придуманной мной только что базы Bingo-Bongo проводит сравнения, то там побеждает — кто знает правильный ответ? — там побеждает Bingo-BongoDB. Да, всегда. Удивительно! Неважно, какое сравнение идет. Меня смущает этот результат. Я не готов сразу доверять ему просто так. Вообще, я очень доверчивый человек по жизни, но когда я надеваю кепку инженера, я сразу начинаю во многом очень сомневаться. Например, вот в таких обзорах.

Другой интересный момент, который меня посмешил, но я его часто видел. Что нам нужно сделать, чтобы правильно сравнить разные СУБД между собой? Конечно же, взять разные данные. Самое смешное, когда одна статья ссылается на другую статью, говорит: «Вот там они получили такую цифру, а мы такую цифру. У них там были одни данные — у нас другие данные. У них одни сервера — у нас другие сервера». Вообще, а что вы сравниваете-то? Тоже не очень приятно.

Есть и более хорошие источники, в конце слайдиков для желающих будет ссылка на то, что мне понравилось как раз.

И большая часть авторов говорит, что, если вы хотите действительно выбрать грамотно, решайте вашу задачу, не смотрите, какие данные у них и какие профили нагрузки у них. Возьмите ваши профили нагрузки, возьмите ваши данные и меряйте только на них. Только эти цифры, и то не на 100% уверенности, вам дадут представление о том, как это будет работать дальше, длительное время. Почему не на 100%? Скорее всего, если у вас система должна работать два года, вы вряд ли будете два года ее тестировать сначала. У вас сроки тестирования будут более ограничены. Поэтому все равно опасность есть, но она, конечно, сильно уменьшается.

Давайте о критериях. Что мы будем сравнивать?

Выбираем СУБД для хранения временных рядов - 12

Я выбрал для своей задачи самые важные. Тут не все критерии, по которым можно проводить сравнение. Я не буду говорить, какие я отбросил. Давайте, я скорее оставлю это на дополнительные вопросы: «А почему вы не сравниваете по этому критерию?». Я расскажу про то, про что сравниваю.

  • Например, пропускная способность на запись. Для меня это важно. Мне нужно успевать, чтобы оно сохранялось, падало на диск и выдерживало те нагрузки, которые у меня прописаны. Но вопрос оказался очень непростой, невероятно непростой. Когда я вижу где-то статью, где говорят: «Пропускная способность столько-то», я начинаю сомневаться — а в каких условиях тестировалось? Потому что, на мой опыт, там всегда зависимости. Например, она меняется с размером «батча» (сколько в пакете данных за раз мы пытаемся туда записать). Она меняется от количества клиентов, которые пишут в базу данных. Она даже немножко разная, если мы долго пишем в базу данных. Например, если мы пишем 5 минут, может быть одна цифра, а если 12 часов, то там могут появляться другие цифры, которые не всегда похожи на то, что называется обычно «пиковая производительность». И, похоже, что этот критерий сам по себе уже не очень тривиален. Его уже можно рассмотреть с разных сторон. Вот эти три стороны (на слайде вверху), с которых я в этом докладе буду рассматривать эту пропускную способность.
  • Дальше, мы же не просто туда пишем. Мы же, наверное, потом будем спрашивать. Мы что-то будем оттуда читать. Поэтому нам важно, чтобы это было достаточно быстро. Для моих задач сравнительно быстро — я расскажу чуть подробнее, когда мы доберемся. Там тоже, правда, надо выделять характерные запросы. Какие запросы характерны для вашей системы? В задаче хранения метрик для индустриальных объектов обычно бывает важно, за какой интервал мы запрашиваем: нам нужна выборка за день, нам нужна выборка за неделю, если очень нужно, нам нужна выборка за две недели или за месяц. Интересно посмотреть, как зависит время исполнения от этой величины. Может быть, короткие запросы будет отрабатывать быстро. А что, если нам обычно нужно за неделю, а не за один час? Надо будет смотреть на разных интервалах, поэтому «в зависимости».
  • Очень важная характеристика даже для меня — степень сжатия. Слава Богу, даже по самым хорошим расчетам, эти данные можно уместить на одну машину. Я считаю, мне повезло. Очень повезло, что я могу, потенциально, записать это на одну машину. Может быть, еще с бэкапом дополнительно. Но для того, чтобы все равно гарантировать, что жесткий диск не переполнится — это очень неприятная ситуация, когда на СУБД переполнится жесткий диск — желательно понимать, сколько все-таки конкретно нужно. Потому что если мы знаем объем входной информации, на жестком диске он совсем другой. Он может быть иногда даже чуть больше за счет дополнительной мета-информации и индексов, а иногда сильно меньше, если встроено хорошее сжатие. Поэтому тоже это следует обязательно померить.

Вот наши критерии, вот про них я буду говорить в первую очередь. И начнем мы с пропускной способности, у нас все-таки HighLoad. Это одна из наиболее интересных характеристик, не такая тривиальная, правда, как оказывается.

Перед этим наши «конкурсанты». Мы будем сравнивать вот этих четырех:

Выбираем СУБД для хранения временных рядов - 13

Здесь я сразу хочу описать один интересный момент, который, скорее всего, у многих у вас всплывет. Почему я сравниваю специализированные решения (а это OpenTSDB и InfluxDB — они вот «мы только time series, это наша вотчина, мы ничего больше не умеем хранить практически») с СУБД общего назначения? Ведь, казалось бы, скорее всего ответ будет очевиден, что по многим характеристикам специализированные лучше.

Ответ здесь, на самом деле, вот, я его сразу дам: с одной стороны да, специализированное решение — хорошо, но что, если у вас все решения влазят в нефункциональные требования? Стоит ли вам городить зоопарк разных систем? Ведь, скорее всего, вы будете хранить не только time series, скорее всего, у вас есть еще какие-то метаданные и какие-то более богатые по модели данные. Скорее всего, их тоже надо будет куда-то складывать. Что если не плодить зоопарк специализированных решений, а показать, что одно решение справляется и с тем, и с тем? Поэтому мне было интересно взять и решения, которые, в принципе, уже используются. Для того чтобы посмотреть, насколько они хорошо справятся с данной ситуацией. Для того чтобы, в крайнем случае, не плодить зоопарк.

У кого бывало так, что несколько баз данных в проекте? У кого бывало две? У кого три? У кого четыре? У кого пять? Осталось несколько людей… Это тоже ведь не очень хорошо. Да, коллеги со мной согласятся. Спасибо. Это укладывается в хорошие требования, но для администрирования это не очень удобная вещь.

Вот об этих четырех мы будем говорить.

Чуть-чуть циферок, куда без цифр. Что мы и с чем сравниваем. Здесь тоже этот слайдик очень важный, потому что я хочу такой дисклеймер вставить, и чтобы вы его поняли.

Выбираем СУБД для хранения временных рядов - 14

Я буду сейчас замерять не СУБД. Я буду замерять их в целой связке, то есть я меряю автоматически как бы и клиента. Потому что мне не очень, честно говоря, интересно, как работает СУБД, я их не продаю. Мне интересно, как они будут работать именно в моей задаче, в моей инфраструктуре, с моими клиентами, с чем-то приближенным к реальности.

Поэтому учтите — и это очень важный момент, — что цифры, которые я буду приводить, касаются не чистых СУБД, они еще привлекают все, что здесь описано. То, что там есть Docker (куда сейчас без него, очень удобно, мне нравится). Там есть специфические клиенты, у которых есть очень одна интересная особенность — у них еще не очень оптимизированные драйверы для хранения, поэтому в некоторых местах там могут быть проблемы с драйверами. И это реалии нашего мира — не в каждом языке программирования у нас есть идеальные драйверы для всех СУБД, которые нам нужны. Иногда в этих драйверах — о, Боже мой! — есть баги, иногда эти баги по производительности, и с этим нам тоже нужно справляться и это понимать.

А теперь уже к самому интересному.

Выбираем СУБД для хранения временных рядов - 15

Графики пошли. Про пропускную способность — очень сложная штука. Я долго пытался понять, что же это такое, что это за величина? Это число? Это зависимость? Это, не дай, Боже, интеграл? Слава Богу, оказалось, вроде бы, что нет.

Я попытался сначала все-таки понять, что я буду мерить и как я это сделаю. Давайте, я попытаюсь прояснить, что такое синий график, и как он построен. Это уже о методиках тестирования.

У меня есть «ручка громкости», очень простая — сколько я буду пытаться записывать. У меня там на самом деле две «ручки»: сколько у меня сенсоров в системе, и с какой частотой они логируют свои значения. Например, я могу «крутить» число сенсоров, зафиксировав, что каждый из них логирует раз в секунду свои значения. И тогда я начинаю «крутить ручку» по горизонтальной оси, моя как бы ожидаемая пропускная способность, то есть 20 тысяч — это 20 тысяч сенсоров, и каждый из них раз в секунду логирует значения.

Что такое вертикальная ось, где, собственно, синий график и отложен? Это мы берем «вольтметр» аккуратненький и начинаем мерить: сколько мы реально записали в СУБД? Причем это делать тоже, оказывается, можно разными способами и хитро! Например, здесь каждая точка (ну, они, понятно, с аппроксимацией) получена следующим способом: запускаем с такой нагрузкой на пять минут, каждую секунду логируем, сколько мы записали в эту секунду, строим гистограмму распределений этих точек и выбираем медиану. Очень классная величина, мне она нравится, это такая пропускная способность, левее которой находится ровно половина из вот этих точек, которые мы померили. То есть это нам гарантирует, что, по крайней мере, половину времени мы писали с такой скоростью и не меньше нее.

Иногда можно выбирать среднее, но вот здесь оно даст вам меньшую цифру. Почему? Среднее, просто усреднение, оно чувствительно к выбросам. Что, если у вас там случайно жесткий диск был занят какие-то количества времени, или кто-то еще подключился к вашей системе и что-то там сделал на пару секунд? Тогда у вас могут несколько секунд быть провалы такие неплохие. Среднее — оно очень к этим провалам чувствительно. Я здесь его не стал рисовать, но среднее всегда меньше, и оно в этом случае, на мой взгляд, не показывает примерно реальное положение вещей. Медиана показывает лучше. Мне понятно, что означает. По крайней мере, половину времени мы будем писать «не медленнее, чем столько».

Начинаем подбираться к самому интересному, вы наверно обратили внимание. Вот эта вот пологая линия — уровень. То есть мы «ручку громкости» крутим, а «громче» не становится. Казалось бы, наверное, оно и есть. Вот она — пропускная способность. Больше в эту СУБД записать нельзя, казалось мне сначала, но что, если мы чуть-чуть поменяем способ, как мы пишем? Что если мы начнем писать не по одной точке за раз, а по две точки за раз? Что тогда получится? А получится другой график, красненький:

Выбираем СУБД для хранения временных рядов - 16

Когда на каждый insert, мы делаем bulk insert. Мы вставляем не одну точку, а целых две, и «крутим» ту же самую «ручку». Оказывается, этот порог поднимается. Так что же такое пропускная способность? Синенькая или красненькая? И, вообще, почему так?

Здесь мне на ум приходит глупейший пример, вы меня извините, но мне он как-то близок. Мало имеющий отношение к СУБД. Давайте предположим такую картину, что вечером компания хорошо отдыхает, развлекается и решает отправить кого-то за бутылкой молока. Мне кажется, здесь лучше всего подойдет молоко. Что человек делает? Он одевается, обувается, берет ключи, выходит, спускается на лифте, идет в магазин, ищет полку, берет молоко, подходит к кассе, делает «пик!», берет пакет, бутылку, поднимается, раздевается, приносит в холодильник — все! Мы с вами сделали систему с пропускной способностью «одна бутылка молока за то время, пока он сходил».

Теперь мы подумаем: «А что, если его попросить взять две бутылки молока?». В чем эта разница будет по времени? То, что на кассе будет не «пик!», а «пик-пик!», а все остальное время будет одно и то же. И мы получим систему, которая имеет пропускную способность почти в два раза больше.

Если мы возвращаемся к миру СУБД, то как эта сценка будет выглядеть? Наверное, это подготовка запроса, открытие сокета, установление сетевого соединения, отправка запроса, на стороне сервера парсинг запроса, подготовка его, исполнение, возможно, подъем с жесткого диска, подготовка ответа, сериализация ответа, упаковка, отправка в сокет, на стороне клиента разворачивание и чтение. Наверное, здесь, если тоже попросить записать две точки, а не одну, вот общие кусочки, это позволит нам начать немножко экономить.

Выбираем СУБД для хранения временных рядов - 17

Есть другой интересный подход, оказывается. Другая ось, которую можно «покрутить» — а что, если мы двух человек пошлем за бутылкой молока? Что, если мы будем писать в два потока? Там тоже есть интересный эффект. Мы действительно делаем это быстрее, чем в один, по одной точке. Зелененькая — это два потока, но по одной точке за раз. Любопытно, кстати, что они не наложились друг на друга. Зелененькие чуть-чуть поменьше. Правда, в пределах колебаний, но все равно характерная медиана меньше, чем у красненького.

То есть, есть две оси, можно еще две «ручки крутить». Можно «крутить», сколько мы пишем за раз, и можно «крутить», сколько клиентов у нас пишут в эту систему.

Давайте их «покрутим», это интересно. Вот эти «ручки», их можно «крутить», смотреть что получается. Например, будем «крутить» батчи. Это одна из моих любимых «ручек», она очень проста в реализации, поэтому я люблю ее «крутить».

Выбираем СУБД для хранения временных рядов - 18

Пойдем по другим графикам. Возьмем разные батчи, эмки, и построим наши точки. Тут видно, что для степеней двойки они взяты. Точки построены точно так же: в течение 5 минут длится эксперимент, и высчитывается медиана из всех пропускных способностей в секунду, которые получены. Для двух конкурсантов. Видна интересная закономерность, что, да, оно растет, но, кстати, как-то оно начинает загибаться чуть-чуть, то есть оно явно растет не до бесконечности, может быть, не очень даже линейно. Другой интересный момент — если в каких-то точках они очень похожи и ведут себя примерно одинаково, то в других они начинают немножко отличаться и вести себя по-разному.

Неужели, пропускная способность — это вот эта кривая? Какая-то зависимость? Возможно. Но работать с кривыми, с зависимостями жутко неудобно. Их в таблицы неудобно вписывать. Удобно работать с числами. Что бы нам такое придумать, чтобы взять и превратить каждый из них в циферку, в число, которое удобно мерить: больше-меньше. Потому что всех на этот график неудобно размещать, они могут начать пересекаться. Неоднозначности. Давайте подумаем, как это можно сделать.

Первое что, когда я такое вижу, у меня рука сама напрашивается взять ручку и сделать вот так — провести какие-то кривулинки:

Выбираем СУБД для хранения временных рядов - 19

Как-бы законы какие-то, наверное, зависимости. Потом возникает момент истины. Надо очень сильно напрячься и догадаться, что это за кривулинка может быть. Нужно подобрать что-то, что похоже. Методов подбора есть много. Один из самых простых и мною любимых и применяемых — это немножко поиграться с осями. Что, если мы по оси горизонтальной начнем откладывать не батчи (сейчас надо будет немножко напрячься), а логарифмы от батчей? Логарифмическая ось. Редко кто, может быть, знает, зачем она применяется, но она очень полезна в таких ситуациях, потому что в ней эта картинка выглядит чуть-чуть попроще:

Выбираем СУБД для хранения временных рядов - 20

С прямыми работать удобней. Что, кстати, нам подсказывает, что графики до этого действительно были логарифмами. Прямые понятны. Наверное, даже углы эти можно посчитать. Вот название слайда раскрывает даже, как это делается. Есть не очень сложный метод линейной регрессии, который нам вот эти углы даст, точнее, тангенсы этих улов.

Дальше здесь тонкий момент такой. Он очень дискуссионный, и я очень надеюсь, что кто-нибудь мне потом расскажет, откуда я это взял. Я уверен, что где-то это в свое время описано было и хорошо придумано. А идея вот в чем: давайте вместо того, чтобы брать эти графики, возьмем вот эти углы, а точнее, тангенсы этих углов. Чем угол больше, тем, вроде, лучше, тем циферка больше, тем лучше. Чем угол меньше, тем, вроде, хуже, тем и тангенс будет меньше. То есть мы можем пытаться это отношение порядка здесь вводить более строго.

Например, для наших конкурсантов (это не углы, это тангенсы углов у меня здесь записаны) получились примерно такие измеренные зависимости пропускной способности от размера батча. В данном случае для двух.

Выбираем СУБД для хранения временных рядов - 21

Обобщим на остальных. И сделаем еще один прием.

Абсолютные цифры — 20 тысяч, 100 тысяч, 200 тысяч — они шикарны для рекламных буклетов, но они мне не очень нужны. Я, кстати, знаю единственно, что мне нужен минимум. Я знаю, например, что каждый из конкурсантов по пиковой производительности укладывается в мои нефункциональные требования, даже с запасом, некоторые с большим запасом.

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

Явно видно, что в этой табличке еще есть место, для того чтобы появились другие столбики, по другим критериям. Давайте, попробуем достроить их.

Выбираем СУБД для хранения временных рядов - 22

Например, пропускная способность от числа клиентов. То же самое. Меряем. Только теперь по горизонтальной оси откладываем, сколько потоков пишут у нас, получаем эти точки. Видно, что они немножко начинают дрожать. Здесь можно догадаться, что кривулинки тоже можно провести. Они будут логистическими функциями, то есть с насыщением. Они действительно выходят на такой порог и дальше не идут.

Выбираем СУБД для хранения временных рядов - 23

Почему, кстати так выглядит? Почему так странно? На самом деле, у нас природа ограничена и, например, на машине, на которой тестируются, а точнее, еще средой ограничено количество ядер, которое может потреблять СУБД. И, я думаю, из этого графика сразу видно, какое это количество ядер.

Я подсказываю. А, давайте, попробуйте задуматься и давайте сейчас все вместе скажем, сколько ядер выдано этой СУБД? Раз, два, три? Четыре? Некоторые угадали, действительно четыре.

Как только ядра заканчиваются, начинается жуткая конкуренция, и работать в этой области фактически уже лишено смысла. Работать надо в области раньше, поэтому здесь я использую другой подход. Я не хочу мерить эти кривые целиком, я хочу мерить только в тех частях, где они линейны, где еще нет этой жесткой конкуренции. Мало ли, у меня эта машина с четырьмя ядрами, а что, если я перенесу на 20 ядер, а что если кому-то очень везет, у него 60 ядер. Там, наверное, будут другие кривые, поэтому здесь я буду мерить только линейную часть. Вот там вообще ложится более-менее на какой-то линейный кусочек.

Выбираем СУБД для хранения временных рядов - 24

И прием тот же самый — прямая, тангенс угла наклона — вот она цифирь. Можем получить циферки зависимости, образно, пропускной способности от числа клиентов, как я предлагаю в этом докладе это понимать, и заполнить табличку уже оранжевыми прямоугольничками.

Выбираем СУБД для хранения временных рядов - 25

Получить измерение по этой характеристике. Идти дальше и глубже. Например, смотреть, а что бывает под нагрузкой? Там, вообще, происходит самое интересное. Это самые дорогие эксперименты, потому что они длятся по 10, по 12 часов. Мой самый длинный эксперимент, по-моему, трое суток. Для разных СУБД, как они себя ведут. Наблюдаются некоторые интересные общие закономерности. Например, вот это OpenTSDB под нагрузкой в 60 тысяч:

Выбираем СУБД для хранения временных рядов - 26

В принципе, достаточно все предсказуемо, все хорошо. Иногда СУБД уходит по своим СУБД-шным делам, что-то там делает. Судя по логам, она очень активно общается с HBase’ом, то есть HBase что-то очень такое активное делает, потом возвращается. Это, кстати, означает, что к этому надо быть готовым, клиенты должны быть готовы. Это, вообще, хорошая практика, потому что СУБД может немножко «уйти в себя». Если она уходит навсегда — это нам не надо, а немножечко — может. Но в остальное время все хорошо, все стабильно, молодец!

Выбираем СУБД для хранения временных рядов - 27

80 тысяч. То же. Вроде, стабильность достаточна, а даже я вам больше скажу — стабильность здесь понимается немножко формально. Если медиана (иногда называют ее пятидесятипроцентный квантиль) — это значит, половина находится левее, то здесь я мерил девяностодевятипроцентный квантиль. То есть меня интересует, чтобы в 99% всего времени запись в СУБД была на том уровне, на котором я хочу. Вот на 80 тысячах действительно так и есть. В какие-то моменты, конечно, мы можем вываливаться, но они не превышают 1%.

Так вот до сих пор выглядит «OpenTSDB здорового человека».

А вот это «OpenTSDB курильщика»:

Выбираем СУБД для хранения временных рядов - 28

Она может на такой нагрузке работать, но здесь явно девяносто девятый перцентиль, вы видите, это не сто, он явно гораздо меньше будет находиться. «В себя уходит» почаще — можно понять, это все-таки надо выдерживать такие нагрузки. И это означает, что, глядя на такой график, я бы сказал: так, эту штуку под сотней не надо держать в этой установке. Под восемьдесят — держите. Сто на долгое время не включайте! В пиковой нагрузке она выдерживает и больше, но на 12 часов держать сотню я бы не рекомендовал.

И тогда появляется вот этот порог. К сожалению, я не смог его вычислить точно. Эксперименты шли с очень большим шагом. Я останавливался на последнем шаге, на котором вот эта характеристика удовлетворялась. Чтобы на протяжении 12 часов система могла стабильно работать под желаемой нагрузкой.

И появились циферки работы под нагрузкой. Они, естественно, гораздо меньше, чем пиковые, но они в этом смысле чуть более интересны, потому что они описывают, как это будет сутками длиться, а не то, как это будет работать всего лишь пять минут. И вот они синие столбики:

Выбираем СУБД для хранения временных рядов - 29

Чуть-чуть «капитанства», наверное, здесь уже прослеживается. Хотя, если смотреть на других, там видно интересные уже взаимосвязи, об этом еще поговорим мы.

Поехали дальше. Время выполнения запросов.

Выбираем СУБД для хранения временных рядов - 30

Здесь уже, слава Богу, чуть попроще. Откладываем по горизонтальной оси длину интервала, сколько мы хотим. Мы хотим запросить данные — за сутки, за три дня, за неделю хотим выгрузить их себе. Делаем 100 запросов и меряем девяносто пятый перцентиль времени выполнения, то есть я хочу, чтобы 95% запросов у меня выполнялись короче, чем за то время, которое указано там.

Для меня это более важное, поэтому здесь не медиана. Почему? Потому что это самая критичная вещь — это пользователь нажал кнопочку, и крутится кружочек. И меня здесь не устраивает, что у половины кружочек закончит крутиться быстрей, чем за 5 секунд. Я хочу чтобы у 95% пользователей кружочек этот закончил крутиться раньше, чем за отведенное время.

Выбираем СУБД для хранения временных рядов - 31

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

Выбираем СУБД для хранения временных рядов - 32

Да-да, я понимаю, что сначала немножко «капитанства» будет. Я старался все делать честно, сам с собой, по крайне мере, быть честным. И просто привожу результаты, которые я честно получил и даже могу их воспроизвести. Я добивался, чтобы эти результаты воспроизводились, и эти графики не дрожали. Допустим, чтобы такой график в понедельник не сильно отличался от такого графика в пятницу, чтобы они в этом смысле устаканились.

Выбираем СУБД для хранения временных рядов - 33

Про компрессию. Наверное, я практически могу только показать результаты. Измерение очень простое. Загружаем примерный объем трафика за месяц, знаем, сколько он в сыром виде занимает, смотрим, сколько СУБД заняла на жестком диске. Включая всю мета-информацию, даже я не рассматривал, что она что-то может под себя дополнительно резервировать. Здесь я немножко грубо себя вел. Я беру просто — сколько она заняла на диске дополнительно. Получали коэффициент, отношение. И вот он, коэффициент сжатия.

У кого-то он, кстати, был даже больше единицы, потому что много мета-информации, надо еще индексы хранить, надо еще какие-то дополнительные идентификаторы хранить, служебные поля. У кого-то был меньше единицы, видно что работает хорошее сжатие. Особенно для тех, кто знал, что им будут складывать вещественные числа. Да, они их очень хорошо жмут, действительно.

Получили наш промежуточный результат. Вроде бы, да, результат очевиден, но я все равно хотел пойти дальше, я не хотел останавливаться на этом графике. Хотя, здесь уже можно сделать кое-какие выводы. Если ты хотел довести это до какого-то, может быть, автоматизма, воспроизводимости и подумать: «Если бы ситуация была чуть более сложной, что бы я дальше с этими графиками делал?». Что, если бы верхушечки не было, верхнего конкурсанта? Ведь там очень странно. Кто-то в одном хорош, кто-то выигрывает в другом. Как мы можем сделать вот это многокритериальное сравнение?

Выбираем СУБД для хранения временных рядов - 34

Давайте чуть-чуть математики привлечем. Возьмем эту табличку и перепишем ее. Я бы не сказал, что это более удобный, но более удобный для нас, вид. Табличка чисел. Строчки — это наши конкурсанты, а столбцы — это наши критерии, которые были на прошлом графике. Теперь добавим ту вещь, которую я долго ждал и думал, где же мне ее добавить: что мне из этих критериев важнее, чем другие; что более важно, что менее важно.

Я могу, в принципе, уступить место, но коллеги действительно знают. Похоже, подход этот многим знаком.

Этого мы объявляем вне конкурса. Вводим нашу матрицу весов. Дальше, я думаю, вы догадываетесь, что произойдет. Перемножаем. Получаем. Вне конкурса пока убираем.

Выбираем СУБД для хранения временных рядов - 35

Вот он наш победитель.

Что, если мы немножко изменим матрицу весов? Что, если мы выделим что-то более важное?

Выбираем СУБД для хранения временных рядов - 36

Я сначала покажу искусственный пример, нам очень важен второй критерий (это зависимость пропускной способности от числа клиентов). Если мы тогда сделаем все формально, у нас победитель будет уже другой.

Здесь, конечно, это все немножко искусственный пример. Такое небольшое «капитанство», потому что того, кого я исключил вне конкурса, он, вроде бы, и хорош. И когда я получил этот результат, да, мне было сначала немножко стыдно — что я приду к людям, буду им рассказать какие-то лишние вещи, там и так все понятно?

Поэтому я начал искать, может быть что-то, что я не знаю.

Выбираем СУБД для хранения временных рядов - 37

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

Выбираем СУБД для хранения временных рядов - 38

Начал изучать, кто выходил последнее время. Наткнулся на один очень интересный проект. Последний конкурсант, который по рекламным буклетикам выглядел интересно. Исходники можно было почитать, они вменяемые, мне понравились. И было интересно прогнать его через ту же самую цепочку.

Я, наверное, уже только покажу финальный результат, где начали появляться неожиданные эффекты. И уже однозначности такой я в них не видел. Если мы теперь оставим только очевидных лидеров, и попробуем для них такой же прием повести, то там он вполне может иметь смысл.

Выбираем СУБД для хранения временных рядов - 39

В равной степени, когда все равно — у нас один победитель.

Выбираем СУБД для хранения временных рядов - 40

Если мы выделим какие-то критерии, как чуть более важные — он другой. Они начинают меняться. И вот именно здесь мы пытаемся внести нашу субъективность. Смотрите, мы субъективно меряем не-конкурсантов, мы субъективно меряем критерии, по которым нам важно что-то выглядывать. И в зависимости от этого получаем разные результаты.

Выбираем СУБД для хранения временных рядов - 41

В принципе, наверное, это главные мысли, которые я хотел донести, поэтому я перехожу плавно к заключению. К тому же, время у меня уже, я так думаю, заканчивается.

Заключение у меня такое «капитанское», которое я для себя сам пытаюсь сформулировать:

  • проверяйте на ваших данных, на ваших системах — это очень полезно;
  • чуть-чуть математики никогда не повредит, поверьте, она делает вас умнее в глазах других;
  • вот такой интересный момент, который коллеги, судя по всему, хорошо знают — субъективную оценку тоже можно мерить. Главное — знайте, что вы в ней меряете.

В принципе, это все.

Выбираем СУБД для хранения временных рядов - 42

Спасибо за внимание.

Кому интересно, можно пройтись по ссылочкам ниже, а у меня все.

Источники:

  1. Y. Bassil. A Comparative Study on the Performance of the Top DBMS Systemspaper
  2. C. Pungila, O. Aritoni, TF. Fortis. Benchmarking Database Systems for the Requirements of Sensor Readings paper
  3. B. Cooper,, A. Silberstein, E.Tam, R. Ramakrishnan, and R. Sears. Benchmarking Cloud Serving Systems with YCSB – paper
  4. T. Goldschmidt, H. Koziolek, A. Jansen. Scalability and Robustness of Time-Series Databases for Cloud-Native Monitoring of Industrial Processes – paper
  5. T. Person. InfluxDB Markedly Outperforms Elasticsearch in Time-Series Data & Metrics Benchmark – blogpost
  6. Д. Калугин-Балашов. Как выбрать In-memory NoSQL базу данных с умом? - slides
  7. B. Schwartz. Time-Series Databases and InfluxDB blogpost
  8. K. Eamonn and K. Shruti. On the Need for Time Series Data Mining Benchmarks: A Survey and Empirical Demonstration paper
  9. R. Sonnenschein. Why industrial manufactoring data need special considerations – slides
  10. S.Acreman. Top10 Time Series Databases – blogpost
  11. J. Guerrero. InfluxDB Tops Cassandra in Time-Series Data & Metrics Benchmark – blogpost
  12. J.Guerrero. InfluxDB is 27x Faster vs MongoDB for Time-Series Workloads – blogpost
  13. Яндекс открывает ClickHouse - blogpost

Спасибо, я готов ответить на ваши вопросы.

Вопрос: Здравствуйте. Спасибо за доклад. Такой вопрос: когда вы мерили под нагрузкой, во что упиралось все? Упиралась в железо, в память, в процессор? Или это были ограничения самого движка?

Ответ: Это, скажем так, вспомогательная работа, которую движок должен постоянно делать. То есть, понятно, что, скорее всего, запись идет постоянно сначала в память, но надо периодически сбрасывать на диск. И в этот момент начинались просадки. Это было хорошо видно и по логам, и по тому, как система себя вела. Потому что, я здесь не стал рисовать, у меня автоматически писались графики нагрузки на жесткий диск. Они очень хорошо коррелировали с провалами по пропускной способности.

Вопрос: Хотел спросить: а запросы параллельно идущей записи, как с ними дела были?

Ответ: Здесь я пытался сымитировать реальную ситуацию. Вот те графики времени исполнения запросов. Эта система была постоянно и в нагрузке по записи. Я примерно ставил, правда, не сотни тысяч, я брал свои показатели, по-моему, я брал 20 тысяч в секунду запись. Держал ее нон-стоп. Именно в этот момент делал запросы и замерял.

Причем, там я наткнулся на одну проблему. Я сейчас воспользуюсь возможностью еще немножко рассказать.

Сначала у меня все было очень быстро. Я не понимал почему. А потом я понял — я делал одни и те же запросы. А как только я начал рандомно выбирать канал, по которому я запрашиваю, и рандомно выбирать интервал, по которому я запрашиваю — цифры сразу пришли в нормальное русло. И, да, магии не произошло. Это действительно не всегда работает быстро. Особенно, если мы хотим выгрузить данные за неделю.

Вопрос: Вы говорили, что вам не очень интересно, как работает СУБД, но, наверное, вы же с какими-то параметрами, с какими-то настройками их запускали? Я к тому, что, например, у той же OpenTSDB много чего можно «крутить». И у остальных тоже. Вы брали дефолт, или все-таки в OpenTSDB использовали append режим, а не compaction?

Ответ: Хороший вопрос. Спасибо большое. Я на него отвечу так.

Во-первых, конечно, часть меня ленивая, и не хочет возиться подробно с настройками каждой из них. Я прекрасно понимаю, что если взять хорошего DBA, он придет и скажет: «Ты ничего не понимаешь. Вот я сейчас все так сделаю, и все заработает». Но он не всегда у меня есть.

Поэтому мне конечно интересны системы, которые by default себя хорошо ведут. Но где-то я его использовал мэйлинг-листы, писал людям, просил объяснить некоторые факты, которые я обнаруживал. Они мне советовали. В частности, мэйл-лист PostgreSQL очень хорошо посоветовал, что там мне нужно правильно выставить, для того чтобы данные у меня пошли лучше, а артефакты, которые я наблюдал — пропали. В частности, они мне советовали, как правильно используют VACUUM, когда, в каких участках.

OpenTSDB. Нет, append/compaction я не менял. По-моему, я что-то меня в настройках storage, но я сейчас, к сожалению, не помню уже точно что. Но, честно скажу, детальной настройки, прям вот такой, все ручки крутить, я точно здесь не производил. Большая часть — это системы, которые из своих Docker-контейнеров стабильных, стандартных, поставляются и ставятся на систему.

Я согласен с коллегой, да, сравнение не очень корректное, поэтому я говорю: «Я сравниваю не СУБД. Я сравниваю то, как я их использую». Поэтому, может быть, меня это оправдывает, а может быть наоборот. Спасибо.

Вопрос: Павел, можно в продолжение того, как вы их используете, те query (запросы), которые вы давали? Что это за query, используются ли индексы и агрегаты, какие-то возможности баз данных, связанные именно с работой с запросами? Что вы сравнивали?

Ответ: Там несколько подводов я использовал.

Во-первых, которые OpenTSDB, InfluxDB — у них встроенные индексы, поэтому они сразу их используют по времени.

Для остальных я шел двумя путями: первое — я просто строил индекс, хорошо работали запросы, но немножко хуже — запись. И, более того, очень было неудобно, например, данные держать в одной коллекции или в одной таблице. Понятно, она разрасталась моментально. Поэтому, коллеги меня простят, я сделал очень плохой прием, который я очень люблю, я начал дробить по дням просто. На каждый день своя табличка. И индексы не использовал.

После этого у меня, конечно, жутко усложнились запросы, потому что мне теперь нужно было эту информацию протаскивать аж в клиент, зато, например, у меня ротация стала очень простой и очень удобной: DROP — все, DROP — все. И запросы стали хорошо работать и на запись, и на чтение.

Очень глупые запросы, только по временному интервалу. Максимум что, это с агрегацией, допустим, среднее за некоторый интервал, то есть не каждую секунду, а, допустим, среднее за минуту.

Вопрос: Павел, спасибо за интересный доклад. Я хотел такой вопрос задать: Вы вначале сказали, что надо знать свои данные, надо знать свой профиль нагрузки, и мерить на нем, да, и на том железе, которое у вас есть? Почему бы было все не упростить и не померить на нужной пропускной способности, сразу же на нужном размере батчей, сразу же сравнить в таких характеристиках? Не надо было бы выводить эти тангенсы, всю сложную математику делать?

Ответ: Я могу здесь ответить вот как. Да, слава Богу, у меня есть, прямо, документ, там написаны нефункциональные требования. Но я знаю, что они могут меняться. И те 20 тысяч, которые я должен успевать хранить сегодня, через год могут превратиться в 40 тысяч. Поэтому, не смотря на то, что каждый из конкурсантов укладывался в них, мне, конечно, было бы интересно выбрать, то которое выдержит изменение нефункциональных требований. Это раз.

Второе. Размер батча — это очень интересная характеристика. За него надо платить. Чем больше у вас батч, тем больше у вас задержка (latency). Вам нужно где-то создавать буферы, которые будут вносить дополнительную задержку в ваши данные. Поэтому делать их очень большими, если вам latency важно — это, вообще говоря, опасно. Поэтому здесь интересно можно было бы смотреть как раз и с точки зрения минимальных размеров батча, но, поскольку у меня параллельно идет обработка всего этого потока он-лайн, а не читается из СУБД, мне здесь latency был в принципе не важен, поэтому конечно я закручивал потом размеры батчей практически до максимума.

Что, кстати, для разных систем по-разному. Например, OpenTSDB уже хорошо работает на шестидесяти четырех, а вот InfluxDB начинает нормально себя вести от пяти тысяч за раз, когда вы пишете. Кстати, я потом заглянул, в стандартных драйверах это стоит как константа иногда: писать 5 тысяч за раз. А буфер находится в самом драйвере, что мне, кстати, очень не понравилось. Я хочу уметь этим управлять, вообще говоря, то есть, сколько это хранится реально на клиенте, когда это идет в базу. Поэтому, например, для InfluxDB мне пришлось поверх их HTTP-протокола свой драйвер написать.

Вопрос: Расскажите, если я правильно понял, вы настраивали структуру, схему базы для каждой базы по отдельности. А как-то приложения вы пытались подстроить под полученную структуру?

Ответ: Конечно. Особенно, когда я начал применять этот не очень, может быть, красивый подход нарезания по дням каждой отдельной таблички, когда в драйверы поступал запрос на range больше одного дня, им нужно было понимать, что на самом деле его надо разбить или, если база позволяет, сделать запрос сразу по нескольким таблицам.

Вопрос: Попытка использовать асинхронный доступ к базе или пулы? Что-то в этом роде?

Ответ: На запись там почти всегда асинхронно шел. Да, пул использовался, в частности, если это был HTTP-протокол, там старался устроить пул конекшнов, и каждый keep alive, то есть чтобы не повторять их. Наверное, вот это все, что использовалось.

Спасибо!

Контакты

pavel.filonov@kaspersky.com
github
twitter

Этот доклад — расшифровка одного из лучших выступлений на профессиональной конференции разработчиков высоконагруженных систем Highload++, а конкретно — секции «Базы данных, системы хранения».

Любителям экзотики мы можем порекомендовать доклад "Обзор перспективных баз данных для highload" от Юрия Насретдинова на ближайшей Backend Conf.

В этом докладе Юрий рассмотрит несколько перспективных баз данных, которые пока еще не очень популярны, но которые определенно ждет успех в будущем, особенно для highload-проектов. Юрий расскажет о Tarantool, ClickHouse и CockroachDB, о том, как они устроены, и почему он считает, что они в будущем станут стандартом де-факто, как раньше был MySQL, а сейчас — MongoDB.

Автор: olegbunin

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js