LINUX.ORG.RU

Вопрос про дилемму в разработке систем хранения данных. По какому пути пойти? СУБД, таблицы, C++, треш, угар.

 


1

3

Сложно-философский вопрос. Не будем рассматривать транзакции и какую-либо связь между таблицами, то есть не будет слова «реляционные (нет реляций между)». Рассмотрим просто таблицу. Таблица - набор строк, каждая строка - набор строго типизированных колонок. Хранит данные - построчно или поколоночно - неважно - зависит от задачи чтения. Главное, что таблица.

Утверждение: в форму таблицы впихивается очень существенное число разных данных. А которые не впихиваются - впихиваются при допиле движка таблиц специальными хаками, но остаётся внешне таблицей. Например мы хотим хранить key:string=[множество-uint64]. Возможно для какой-то задачи, оптимально будет сохранить и на диске и в памяти структуру данных вида (key_len, key, потом тупо последовательность всех uint64 отсортированных). И рядом хеш-табличку по key возможно. Но если бы мы записывали это в таблицу, у нас бы было N число строк вида (key, uint64), где N - число разных uint64, а key бы повторялся. Сходу это выглядит неоптимальным, потому что кучу раз key повторили, но умная таблица не будет хранить повторяющиеся key и получится так же оптимально, как в наивном подходе и расположит всю таблицу прямо как в примере выше - не как последовательность кортежей (SEE_PREV_VALUE, uint64), а прям как один список (uint64, uint64, …., uint64). Я ж говорю - с хаками, но таблица.

А теперь вопрос. Предположим вы бекенд-C++-тимлид в каком-то инновационном банке (которому не жалко рискнуть наняв вас, а не поставив везде Oracle) или в каких-нибудь там одноклассниках или в гугло-яндексе. Тут давайте не будем вспоминать, что в этих организациях реально используется или говорить, что все они давно закоренели и там таких опытов не ставят, а работает YDB - пытаюсь показать масштаб.

  1. Предположим у вас есть C++ фреймворк, куда входит сетевой код принятия запросов (протокол-буфферс, например), какой-то движок хранения данных произвольного формата в файлах, код записи-воспроизвдеения WAL, код репликации, код статистики… И этот фреймворк позволяет за 20 минут под нужный формат данных наклепать на коленке новую «СУБД», написав буквально какой-то std::unordered_set в функции main() и «завернув» этот контейнер в данный фреймворк, выдав к нему доступ из сети и сериализацию/десериализацию на диск целиком и запись в WAL и т.п. То есть, к вам приходят люди, которые хотят хранить key=value, вы оформляете им новую «СУБД» с 2 методами - set и get и катите на прод, все юзают, все счастливы. Приходят другие люди, хотят по 64-битному числу хранить множество из миллиона других 64-битных чисел и искать в нём. Вы тоже быстро фигачите какую-то структуру данных на готовых контейнерах или даже достаёте из закромов какую-то свою супероптимальную, заврорачиваете в фреймворк, куяк-куяк и в продакшен. Не нужна какая-то СУБД - выкинули, не жалко, кода было мало.

  2. И у вас есть второй вариант: сделать один хороший табличный «движок». Все эти клиенты получают всегда одно и то же представление, один и тот же интерфейс (возможно даже SQL). В особо упоротых сценариях вы дорабатываете этот движок под их формат данных (доработка повышает эффективность использования памяти/диска данной таблицей) и эта доработка оформляется просто в отдельный типа индекса или в некое хитрое слово, указываемое на этапе CREATE TABLE.

По какому пути вы бы двигались и ПОЧЕМУ?

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

  2. Выглядит тоже круто, поскольку многие моменты унифицируются. Тайм Ту Маркет ещё ниже - не надо даже ждать пока под твою структуру данных разраб почешется и напишет новый (хоть и крошечный) код, ты можешь уже сейчас CREATE TABLE и в 95% случаев тебе хватит. Не хватит - тогда и придёшь ныть-оптимизировать. Универсальные моменты: способы доступа, способы анализа, язык общения между командами (все говорят про таблицы, а не каждый про свою абстрактную опердень, выраженную в каждый раз новом C++ коде), способы конвертации данных (переливка между таблицами - это понятнее, чем писать конвертеры данных между одним форматом (1) и другим форматом (1) и т.п., проще дорабатывать всякие автоматические решардинги или переливаторы данных - один раз сделали для таблиц и работает у всех, не надо каждый раз думать как оригинальный формат данных (1) обрабатывать. В конце-концов, можно сделать DROP COLUMN, что в случае (1) оборачивается жестью и конвертацией старых данных).

Спасибо.



Последнее исправление: lesopilorama (всего исправлений: 1)

Слишком много слов. Приведи в порядок свои мысли и попробуй снова. Если не умеешь приводить в порядок свои мысли - плати деньги тем, кто будет делать это за тебя.

alex1101
()

И этот фреймворк позволяет за 20 минут под нужный формат данных наклепать на коленке новую «СУБД»

Какие влажные мечты… Не, ну Вы можете попытаться конечно - «флаг в руки», что называется. Выгорит - озолотитесь, гарантирую.

сделать один хороший табличный «движок»

Осталось найти и «выбить» ресурсы на разработку сопоставимые с ресурсами того же Оракла…

bugfixer ★★★★★
()
Ответ на: комментарий от bugfixer

Какие влажные мечты… Не, ну Вы можете попытаться конечно - «флаг в руки», что называется. Выгорит - озолотитесь, гарантирую.

Почему мечты. Представьте яндексовский как там его… не помню, новый C++ фреймворк для разработки сетевых приложений. Там всё есть, что позволяет клиентам получить доступ к вашему C++ коду. Вы просто пишете std::map<int, int>, делаете к ней обращения из сетевых вызовов и движок key:int = value:int готов.

Что с хранением данных не знаю, но аналогично. Представим, что в яндексовском фреймворке есть способы записи данных на диск и чтения из него: тогда вы просто каждый сетевой запрос пишете в WAL прямо в том виде, в котором он пришёл, а на старте читаете WAL. Профит.

lesopilorama
() автор топика

Подобные вещи делаются путем расписывания двух вариантов и сравнения плюсов и минусов с учетом ЦЕЛИ, которую нам надо достигнуть. Но поскольку в ОП сферические фичи для сферических клиентов, которым надо нечто сферическое в вакууме, то это сделать трудно.

goingUp ★★★★★
()
Ответ на: комментарий от bugfixer

Потому как Вы не до конца понимаете что Вас ждёт, буквально, «прямо за углом».

Если б понимал, то наверное не задавал эти все вопросы. У вас есть возможность об этом рассказать, зачем ждёте приглашения)

lesopilorama
() автор топика
Ответ на: комментарий от lesopilorama

Если б понимал, то наверное не задавал эти все вопросы

Эта часть у меня вопросов не вызывает

У вас есть возможность об этом рассказать, зачем ждёте приглашения)

И да и нет. Я очень сильно скован NDA, и, вообще, злостный пропраетарщик. Но могу говорить с колокольни project manager’а и активного maintainer’а узко специализированной распределенной базёнки принимающей несколько терабайт новых записей в день. Если Вам хватает Оракла: лучший совет - используйте Оракле, и не выпендривайтесь - нужны очень веские причины писать что-то своё.

bugfixer ★★★★★
()

Не будем рассматривать транзакции и какую-либо связь между таблицами в форму таблицы впихивается очень существенное число разных данных.

А в чем тогда смысл? Запихать данные в данные ради данных?

Выборку-то как делать? По ключу? Тогда скажу что чистый «Key-Value» - убожество, которым очень мало чего можно сделать.

А все что выше так или иначе приходит к реляционности, посмотри на путь той же MongoDb, в которой теперь и ACID и JOINы в полный рост.

В чем смысл-то?

alex0x08 ★★★
()
Ответ на: комментарий от lesopilorama

Ну ты либо начинай, либо че.

Изначально был поставлен вопрос в терминах «табличек». Таблички сами по себе без привязки по primary key, constraints, ACID и всего вот этого - ничего не стоят. А пока имеется устойчивое ощущение что Вы BerkleyDB изобрести пытаетесь.

bugfixer ★★★★★
()
Ответ на: комментарий от alex0x08

А в чем тогда смысл?

Селектить из таблицы во всех приложениях для всех типов данных, вместо обращения каждый раз в новый микросервис со своим протоколом. Универсализация. Возможность оперирования понятиями индекс. На две первые колонки один примари, а на десятую - ещё один если надо. Смыслы описаны в пункте 2.

lesopilorama
() автор топика
Ответ на: комментарий от bugfixer

Изначально был поставлен вопрос в терминах «табличек». Таблички сами по себе без привязки по primary key, constraints, ACID и всего вот этого - ничего не стоят.

Ну, стоят. Главным образом из-за унификации: «всё - таблица». Разрабов не надо учить работать с разносортными микросервисами, а надо просточтобы они умели в селект «как в мускуле» и сказать им имена таблиц. Плюс возможность смены схем данных на леиу без переписывания сишных структур. И т.п. Эсиды и транзакции и ограничения и реляции - в большом числе мест нафиг не требуются.

Можно считать, что я говорю о key=value, в котором key - тот набор колонок, который входит в PK, value - все остальные.

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

lesopilorama
() автор топика
Ответ на: комментарий от alex0x08

Тогда дальше обсуждать не стоит, надо садиться и писать прототип в коде. Не смею мешать гению

Да не обязательно так торжественно обьявлять о выходе из чата, на пхоруме ещё много специалистов, без ответа не оставят)

lesopilorama
() автор топика
Ответ на: комментарий от lesopilorama

Есть вещи, которые нельзя объяснить при всем желании - их надо обязательно «прочуствовать» на своем опыте, самому. Поэтому садись и пиши код прототипа уже - быстрее дойдет.

alex0x08 ★★★
()
Ответ на: комментарий от alex0x08

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

lesopilorama
() автор топика

сделать один хороший табличный «движок».

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

alysnix ★★★
()
Ответ на: комментарий от lesopilorama

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

Одна из таких стадий выглядит как «создать свое уникальное но универсальное». Специалист видит нечто что с его точки зрения является неоптимальным:

Главным образом из-за унификации: «всё - таблица». Разрабов не надо учить работать с разносортными микросервисами, а надо просточтобы они умели в селект «как в мускуле» и сказать им имена таблиц

Дальше есть всего два варианта:

  1. попробовать сесть и реализовать, приложив максимум усилий. Да, в итоге будет обсер, но в процессе родится мудрость и переход на следующий уровень понимания.
  2. продолжать спамить на форумах и так и остаться «непризнанным гением», коих в отрасли разумеется большинство.

Вообщем ничего нового тут нет, все это уже было.

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

alex0x08 ★★★
()
Ответ на: комментарий от alysnix

с транзакциями, репликациями, масштабируемостью, устойчивым к сбоям и полным фаршем?

  1. В посте ведь сказано, что транзакции не интересны. Транзакции сами по себе никак не связаны с представлением данных - транзакции могут быть и в редисе и в монгодб.

  2. Масштабируемость - опять же задача ортогональная и нужная всем одинаково. Все её хотят, даже в примитивных key=value.

  3. Репликация - это просто копирование WAL на другой сервер, ничего сложного как раз.

В общем, мы говорим только о форме представления данных. Таблица не означает ничего большего, кроме таблицы. Я даже специально сказал, что нет слова «реляционная», т.к. ничто ни с чем никак не относится, нет отношений (реляций) - foreign key или как там его и подобной связи между таблицами. Нет джоинов. Мы говорим только о таблицах. Наша СУБД даже не в курсе про БД, то есть там даже нет иерархии «БД -> набор таблиц». У нас просто «набор таблиц». Глобальные имена таблиц на всю корпорацию без указания БД.

lesopilorama
() автор топика
Ответ на: комментарий от alex0x08

Наверное вы меня поняли слишком «розово-понично»: мол я в мире розовых пони размечтался о революционном универсальном и хорошем. Нет, я о более простом - о «табличном представлении данных» VS куча-микросервисов-со-специфическими-структурами-данных-внутри.

Транзакции - не хочу, джойны - не надо, самошардирование - ортогонально и сложна-сложна одинаково везде, репликация - это везде одинаково и не сложно. Так же нет речи про PAXOS, RAFT, viewstamped replication.

lesopilorama
() автор топика
Ответ на: комментарий от lesopilorama

Нет, я о более простом - о «табличном представлении данных»

Мы все очень внимательно слушаем.

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

Эвона как.

bugfixer ★★★★★
()

По какому пути вы бы двигались и ПОЧЕМУ?

ни по какому

потому что теорема эскобара.

хочется универсальности - храни JSON, средства работы с ним вкрячены повсеместно, включая СУБД всевозможного разлива. REST и JSON наше всё. изобретать свои велосипеды не возбраняется, но аргументы к тому должны быть крепкими, как первичные половые признаки молодожена в первую брачную ночь.

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

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

а «памагите с первого раза попасть в самую дырдочку» это вообще ни о чем и никакого полезного выхлопа тебе не даст.

крч сворачивай эту богадельню и вали трудиться. принесешь прототип - поговорим.

olelookoe ★★★
()
Ответ на: комментарий от olelookoe

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

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

Дальнейший высер нечетал, он какой-то нравоучительный опять. Нахер вас, глядящих на меня с высоты своего опыта, у меня больше всё равно)

lesopilorama
() автор топика
Ответ на: комментарий от lesopilorama

Вы хотите сказать, что главное сделать таблицы, а транзакции-масштабируемость-репликации, джоины и прочие ACID наростут, не сложно будет добавить? Или что вам это все для задач ваших и ваших клиентов не нужно?

goingUp ★★★★★
()
Ответ на: комментарий от goingUp

Вы хотите сказать, что главное сделать таблицы,

Речь только о представлении данных. Разговор про (1) «таблицы для всего» VS (2) «самописные C++ демоны со своими структурами данных для каждого типа данных».

Транзакций и джоинов в (2) и так нет, не об этом речь.

lesopilorama
() автор топика
Ответ на: комментарий от lesopilorama

Ну то есть (1) ad-hoc решение для каждого клеента или (2) использовать НАРАБОТКИ. Ну, в сферической ситуации в вакууме 2 может покрыть уже готовая СУБД, скажем постгрес, а 1 имеет смысл в очень нишевых ситуациях. Так что какое-то 3)

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

goingUp ★★★★★
()
Ответ на: комментарий от lesopilorama

мол я в мире розовых пони размечтался о революционном универсальном и хорошем

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

о «табличном представлении данных»

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

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

Вот теперь распиши как ты будешь это реализовывать со своим подходом.

alex0x08 ★★★
()

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

lesopilorama
() автор топика
Последнее исправление: lesopilorama (всего исправлений: 2)
Ответ на: комментарий от lovesan

Тимлиды же обычно пашут больше всех

Так и есть. А ещё они берут на себя ответственность за своих подопечных. И иногда - ну очень интересные ситуации возникают…

bugfixer ★★★★★
()
Ответ на: комментарий от lesopilorama

ничего сложного в жонглировании колонками в таблице нет - захотел - добавил, захотел - удалил.

Тогда берите себе вертику или кликхаус и кидайте сырые не структурированные данные. Должно надолго под описанное хватить.

Shadow ★★★★★
()
Ответ на: комментарий от lovesan

Это менеджерский вопрос. Тимлиды же обычно пашут больше всех

ТС задаёт вообще не тимовский вопрос, а про архитектурные решения.

Если так всё запущено что это свалили на него, то иначе никак

MKuznetsov ★★★★★
()

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

В продаёте СУБД? Если нет, то берите готовые решения, даже для простых случаев.

Kroz ★★★★★
()

Ты можешь взять YDB и использовать как путь (1) так и путь (2). Правда в первом случае тебе надо будет спускаться на слой «таблеток» и оформлять свой код в новый бинарь.

Reset ★★★★★
()
Ответ на: комментарий от lesopilorama

Потому как Вы не до конца понимаете что Вас ждёт, буквально, «прямо за углом».

Если б понимал, то наверное не задавал эти все вопросы.

Зависит от требований и архитектуры. Но я могу попробовать.

Как вы планируете решать split-brain проблему? Если что это ситуация когда две реплики (у вас же high availablilty, так?) сервиса который управляет данными теряют между собой связь (например, проблема на сети), каждая реплика теперь думает что другая недоступна, и каждая реплика становится мастером?

Как вы планируете решать проблему миграции данных, когда при очередном апгрейде придётся поменять дата-схему?

Ваш C++ фреймворк умеет в бекапы? И как это будет работать если параллельно с бекапом кто-то будет добавлять/изменять/удалять записи?

Как с работой под нагрузкой? Тесты проводились? Ограничения задокументированы? Что будет если отправить 1 000 одновременных запросов на завись или чтение? Что если ключ или значение будет, скажем 1Gb? Какой timeout на запрос на чтение и на запись? Если какой-то запрос будет отрабатывать 1 час, какие есть у клиента средства чтобы понять причину?

Как с документацией? Кто-то кроме вас (вашей команды) сможет поддерживать и развивать ваш C++ фреймворк? Что будет когда больше половина вашей команды уволится (не обязательно в один момент) или компания попросит передать поддержку вашего фреймворка другой команде?

Поддержка вашего C++ фреймворка - это ваша основная деятельность? Делаете ли вы регулярные аудиты на уязвимости, обновляете ли вы регулярно зависимости (если они есть) когда какая-то версия зависимости прекращает срок своей жизни?

Это навскидку…

Kroz ★★★★★
()
Последнее исправление: Kroz (всего исправлений: 1)
Ответ на: комментарий от Kroz

Как вы планируете решать проблему миграции данных, когда при очередном апгрейде придётся поменять дата-схему?

Если речь про вариант (1), то никак. Если очень надо, то кодить на С++ конвертер данных и т.п. гимор. Этим (2) и хорош - alter table просто.

lesopilorama
() автор топика
Ответ на: комментарий от Kroz

Ваш C++ фреймворк умеет в бекапы? И как это будет работать если параллельно с бекапом кто-то будет добавлять/изменять/удалять записи?

Там просто снепшоты, например. Любой файл на диске без суффикса .inprogress в имени - можно просто взять и унести в бекап. А бекап WAL - это просто его инкрементальное копирование в бекапилку (или другую реплику). Это как раз не самая сложная часть.

lesopilorama
() автор топика
Последнее исправление: lesopilorama (всего исправлений: 1)
Ответ на: комментарий от Kroz

Как с работой под нагрузкой? Тесты проводились? Ограничения задокументированы? Что будет если отправить 1 000 одновременных запросов на завись или чтение? Что если ключ или значение будет, скажем 1Gb? Какой timeout на запрос на чтение и на запись? Если какой-то запрос будет отрабатывать 1 час, какие есть у клиента средства чтобы понять причину?

Это всё уже вопросы немного не по теме. Они про то «реально ли ли ваша (1) хороша». Не об этом тред. (1) одинаково плоха, как гипотетическая (2), потому что написаны одними и теми же людьми. Внутри (1) лежит простой std::unordered_set<std::string> (или самописный аналог, умеющий то же самое более эффективно по памяти). Доступ к этому контейнеру делается в один поток. И там 3 операции - insert, erase, get. Тут всё настолько примитивно, что какбэ даже неинтересно. Один запрос не может работать дольше долей микросекунды, параллельных не бывает. Будут параллельные - пошардим данные и запустим ещё 100 экземпляров этой опердени. Ну и лимит на key_size/value_size = 256 байт и это написано крупными буквами на морде микросервиса. Всё скучно и тупо.

В случае (2) у нас бы была таблица вида (key:string, value:string) с теми же лимитами, с тем же одним потоком. SELECT в этой таблице дольше долей микросекунды бы тоже не умел работать.

Речь в треде идёт о крайне скучных тупых примитивных запросах, никаких там джойнов на миллиард минут, никаких планировщиков запросов.

Про клиентов: их нет, кроме внутренних корпоративных backend-разрабов, посылающих на питонячке запросы на сервера с (2) или с (1). Если этим клиентам что-то не нравится, их просто увольняют нах и готово.

Ещё раз: ВСЁ СКУЧНЕЕ ЧЕМ ВЫ ПОДУМАЛИ. Примерно как в армии.

lesopilorama
() автор топика
Последнее исправление: lesopilorama (всего исправлений: 6)