Pull to refresh

Comments 339

Наверное СУБД — это все же инструмент. И в зависимости от задачи мы берем тот или иной инструмент (это кстати и к голосованию относится). Универсальных СУБД не существует.
Наверное СУБД — это все же инструмент. И в зависимости от задачи мы берем тот или иной инструмент (это кстати и к голосованию относится)
Это сферическое «правильное» утверждение в вакууме. На практике один хороший шуруповёрт легко заменяет десяток инструментов для разных задач (от миксера до перфоратора).

Универсальных СУБД не существует.
Обоснуйте, пожалуйста :-)
Возьмите шуруповёрт и попробуйте им проперфорировать бетонную стену. Тоже самое в случае с базами.
Или вот ещё один универсальный инструмент, который я недавно себе приобрёл:

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

У меня в каждый конкретный момент задачи ограничены.

Тем больше точек отказа.

… и тем меньше опасность отказа каждой точки.
> У меня в каждый конкретный момент задачи ограничены.

Только ящик с инструментами бездонный :-)

> … и тем меньше опасность отказа каждой точки.

Тем больше вероятность отказа хотя бы одной точки. Так и будете спорить с тем, что простые решения надёжней? :-)
Только ящик с инструментами бездонный :-)

Не вижу в этом ничего плохого. Особенно в случае с ПО.

Так и будете спорить с тем, что простые решения надёжней?

Понятие «надежности» нынче не так однозначно, как вам кажется. Какая система «надежнее» — та, которая падает с вероятностью 25%, но вся, или та, в которой с вероятностью 50% происходит потеря части функциональности?
Не вижу в этом ничего плохого. Особенно в случае с ПО.
В случае ПО вы тратите время на интеркоммуникацию и поддержку разных инструментов.

Понятие «надежности» нынче не так однозначно, как вам кажется.
Я понимаю, что попираю устои, но вы не могли бы вести себя менее спесиво? Спасибо.

Какая система «надежнее» — та, которая падает с вероятностью 25%, но вся, или та, в которой с вероятностью 50% происходит потеря части функциональности?
Та, в которой не происходит при этом потеря данных и их согласованности :-)
В случае ПО вы тратите время на интеркоммуникацию и поддержку разных инструментов.

Вместо того, чтобы тратить его на попытки забить гвозди гантелей. Я считаю, это выигрыш.

Та, в которой не происходит при этом потеря данных и их согласованности

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

Для простоты — в обеих.
В одной ACID СУБД потерь не будет. Но если вы будете использовать «на каждый чих свой инструмент», то без услуг СУБД без ACID явно не обойдётесь.
Вы забиваете даже шурупы (деревья, графы) молотком (РСУБД),

Вы не знаете, что, где и как я делаю.

а я вам предлагаю шуроповёрт (мультимодельную СУБД)

А эта ваша мультимодельная СУБД умеет реляционную модель?

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

(А вы все еще держитесь за ACID?)

Вопрос был не в этом, а в том, что есть две системы с разными вероятностями отказа (и последствиями этого отказа). Для простоты обсуждения ACID-гарантии у них одинаковые. Какая из них «надежнее»?
А эта ваша мультимодельная СУБД умеет реляционную модель?
Джойны не умеет за не надобностью. Эквивалент таблицы из SQL — класс. orientdb.com/docs/last/Tutorial-Document-and-graph-model.html

А вы все еще держитесь за ACID?
А чего б не держаться за хорошие вещи?

Вопрос был не в этом, а в том, что есть две системы с разными вероятностями отказа (и последствиями этого отказа). Для простоты обсуждения ACID-гарантии у них одинаковые. Какая из них «надежнее»?
При прочих равных комбинация двух технологий не может быть надёжней одной. OrientDB, например, образует аналог RAID но для баз данных, так что отказ одного узла не фатален.
Джойны не умеет за не надобностью. Эквивалент таблицы из SQL — класс.

Она еще и индексные оптимизации не умеет (если я, конечно, ничего не путаю).

Та самая ситуация, когда вы мне предлагаете шуруповерт вместо перфоратора… а у меня несущая бетонная стена.

А чего б не держаться за хорошие вещи?

Стоимость реализации?

При прочих равных комбинация двух технологий не может быть надёжней одной.

А откуда вы взяли «комбинацию двух технологий»? Я, вроде бы, говорил о системе в целом.
Индексные оптимизации — это вы о чём?

Та самая ситуация, когда вы мне предлагаете шуруповерт вместо перфоратора… а у меня несущая бетонная стена.
Нет нет, если у вас такая прочная стена, то вам стоит в дополнение к универсальному шуруповёрту приобрести перфоратор. А вот дрель можно и не покупать.

Стоимость реализации?
Если стоимость данных меньше стоимости ACID, то да, можно и поиграть с ненадёжными инструментами :-) Но по мне так чем меньше непредсказуемости тем лучше, так что без веских аргументов я бы не стал отказываться от ACID.

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

Вот об этом:

SELECT COUNT(*) FROM SomeData WHERE SomeField = 15


Работает себе из коробочки полным перебором таблицы. Стало медленно — построили индекс, и внезапно — не трогая кода! — стало быстрее в разы.

Если стоимость данных меньше стоимости ACID, то да, можно и поиграть с ненадёжными инструментами

Вы так говорите, словно кроме ACID надежных инструментов не бывает.

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

Вот «без лишнего оверхеда» — еще надо доказать.

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

Ориент тоже поддерживает индексы разных типов: orientdb.com/docs/last/Indexes.html

Вы так говорите, словно кроме ACID надежных инструментов не бывает.
ACID — это и есть различные аспекты надёжности, без которых данным полученным из БД нельзя доверять.

Я привел конкретный пример — вы до сих пор не можете ответить, что происходит с надежностью системы.
Мы ходим по кругу. Мне нечего добавить к тому, что я уже сказал.
Ориент тоже поддерживает индексы разных типов: orientdb.com/docs/last/Indexes.html

Какой-то из них работает так, как описано в моем примере?

ACID — это и есть различные аспекты надёжности, без которых данным полученным из БД нельзя доверять.

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

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

Я так понимаю, это про индексы… вы, конечно же, можете показать, где в документации написано, что с момента построения индекса по полям все запросы по этим полям автоматически попадают в индекс?

Он дорог лишь при большом числе реплик, но не шардов.

Ровно наоборот. Количество реплик не влияет на стоимость ACID (если вы, конечно, не включаете в ACID write-quorum, которого там не было изначально). А вот каждый шард — это, потенциально, новая нода в распределенной транзакции.

(да, а еще бывают распределенные транзакции между несколькими экземплярами/системами)
Я так понимаю, это про индексы… вы, конечно же, можете показать, где в документации написано, что с момента построения индекса по полям все запросы по этим полям автоматически попадают в индекс?
Интересно, почему вы сомневаетесь, что это так? :-) Индексы работают также как в любой РСУБД. Можете проверить это explain-ом.

Количество реплик не влияет на стоимость ACID (если вы, конечно, не включаете в ACID write-quorum, которого там не было изначально).
Куда ж без него? Если кворум не будет достигнут, то транзакция не пройдёт, а мы уже отчитались, что прошла.

А вот каждый шард — это, потенциально, новая нода в распределенной транзакции.
А реплика — гарантированная новая нода в распределённой транзакции.

(да, а еще бывают распределенные транзакции между несколькими экземплярами/системами)
А мы сейчас о чём говорили?
Интересно, почему вы сомневаетесь, что это так?

Потому в документации написано, что обращение к индексу делается через префикс, и нигде не написано иного. Если это не так — прекрасно.

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

Это если кворум на запись больше единицы.

А реплика — гарантированная новая нода в распределённой транзакции.

Только если вы используете стопроцентный кворум на запись.

А мы сейчас о чём говорили?

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

Это если кворум на запись больше единицы.
Если кворум меньше большинства.

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

Это само по себе ни о чем не говорит и ничего не обещает.

Если кворум меньше большинства.

Эээ… вы как-то по-своему понимаете кворум. Write quorum — это число реплик, которые должны рапортовать, что запись прошла успешно, прежде чем она будет признаной успешной системой в целом. Большинство тут ни при чем. Соответственно, транзакция становится распределенной в тот момент, когда write quorum больше единицы.

Имеются ввиду транзакции между разными СУБД?

Между разными системами — СУБД не единственный транзакционный ресурс.

Ну, я про такие не слышал.

А зря. Они есть, и они составляют немалую головную боль.
Транзакция становится распределённой, когда затрагивает несколько узлов. Моё замечание про большинство касалось случая отката транзакции. Если вы не дожидаетесь завершения транзакции (writeQuorum < majority), то получаете нарушение Durability.

Не слышал — в смысле реализаций такого в СУБД, а не вообще.
Не слышал — в смысле реализаций такого в СУБД, а не вообще.

В MS SQL есть, например. Другое дело, что все равно эта реализация рано или поздно упирается в ограничения (или принципиальную невозможность), и вы вынуждены делать систему, не имеющую ACID в одной из точек. После этого, внезапно, становится понятно, как работать с системами, которые имеют очень ограниченные ACID-гарантии.
Через компенсации и eventual consistency. Если грубо, то аналогично тому, как проходят списания по пластиковым картам.
Ну то есть путём усложнения процессов. В случае гетерогенных систем это необходимость. Но стоит ли самому себе вставлять палки в колёса?
Во-первых, почти любая сложная система в бизнесе — гетерогенная (по крайней мере, в моем опыте всегда получалось так). Во-вторых, ей достаточно быть распределенной (две БД одного производителя, не состоящие в кластере), чтобы эти проблемы начали проявляться.

В-третьих — CAP-«теорема».
Поэтому давайте напихаем побольше разных no-acid систем, чтобы «всё как у взрослых»? :-)

Вот именно, что «теорема» :-)
Поэтому давайте напихаем побольше разных no-acid систем, чтобы «всё как у взрослых»?

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

Вот именно, что «теорема»

Опровергнуть ее тоже пока никому не удалось. Собственно, OrientDB ей удовлетворяет.
И всё же тем, что дают ACID стоит, отдать предпочтение.

(http://habrahabr.ru/post/231703/)[Давайте не будем снова вспоминать эти глупости.] :-)
И всё же тем, что дают ACID стоит, отдать предпочтение.

Ну да, нам всем хочется жить в идеальном мире.

Давайте не будем снова вспоминать эти глупости

Ничего глупого в CAP нет. Она просто помогает правильным образом понимать некоторые компромисы.
Скорее запутывает, внося неожиданные определения привычных терминов.
Множественное число лишнее — только consistency. Ну и да, ничего неожиданного в использованном там определении, если смотреть на распределенные системы, нет.

В частности, как уже говорилось, Orient не поддерживает consistency в понимании CAP-теоремы, и при этом еще и отказывается от availability при сетевом отказе… так себе компромис, будем честными.
В Ориенте это всё гибко настраивается: http://www.slideshare.net/lvca/orientdb-distributed-architecture-11
Его можно сделать полностью строго консистентным при распределенной архитектуре? А как тогда понимать следующую фразу из документации:

During the distributed transaction, in case of rollback, there could be an amount of time when the records appear changed before they are rollbacked.

«In case one or more nodes fail on commit, the quorum is checked. If the quorum has been respected, then the failing nodes are aligned to the winner nodes, otherwise all the nodes rollback the transaction.»
Ну то есть, если не используются локи и master-slave конфигурация, то такая ситуация вполне возможна из-за конкурирующей транзакции.
А если используется мастер-слейв, и связь между мастером и слейвом нарушена — что будет при записи?
На сколько я понимаю слейв будет выкинут из кластера и все клиенты переподключатся к мастеру.
… это если мастер доступен оттуда, откуда клиенты стучались к слейву.

Но, как видите, ориент прекрасно иллюстрирует треугольник CAP: при отсутствии сетевой связности вы можете иметь либо консистентную систему, пожертвовав доступностью и производительностью (пример с мастер-слейвом), либо HA/HL-систему, пожертвовав строгой консистентностью (пример с мульти-мастером и, желательно, кворумом меньше 100%)
Не уверен можно ли в Ориенте сделать так, чтобы слейв давал отлуп при потере синхронизации.

Как видите вы сами, гаворя о CAP, используете другие термины (консистентность, доступность, производительность). А то что мы не можем обеспечить синхронизацию, если между узлами нет связи, и как следствие вынуждены выбирать отказывать ли в обслуживании или выдавать устаревшие данные — это очевидно без всяких «теорем».
Как видите вы сами, гаворя о CAP, используете другие термины (консистентность, доступность, производительность).

Как же другие? Consistency, availability. Просто в CAP «производительность» заложена в «доступность», потому что доступность ограничена во времени.
Факт номер 2 в упомянутой мной выше статье как раз об этом :-)
Тогда в чем ваши претензии к CAP? Она есть, и orientdb ее очередной раз подтверждает.
http://habrahabr.ru/post/267079/#comment_8581265
Примеры в студию.
Да, кстати, по поводу «тем больше точек отказа».

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

И вы что-то говорите о бездонном ящике для инструментов? Иметь по две (как минимум) копии каждого инструмента?
Не каждого, а одного универсального. А вот вам для обеспечения того же уровня надёжности придётся дублировать уже каждый специализированный инструмент.
Не бывает совсем универсальных инструментов (вы не замените шуруповертом пилу).

И да, мне не нужен тот же уровень надежности, мне достаточно ситуации, когда при отказе одного инструмента не останавливается весь рабочий процесс.
Не бывает совсем универсальных инструментов (вы не замените шуруповертом пилу).
Конечно, но и задачи-то в большинстве случаев типовые, а не «уникальные».

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

Как уже говорилось выше, у меня есть другие набуренные отверстия. Если нет — ну что ж, горе мне, сегодня я отдыхаю.

(ну или пойду полочки скручивать, для этого мне перфоратор не нужен)
Угу. Моя несущая бетонная стена передает этим «шуруповертам» пламенный привет.
Вы пробовали или теоретизируете?
Эти конкретные не пробовал (а что их пробовать, в них все равно бур на 25 не влезет), а вообще на моей стенке заткнулось три разных дрели (дрели! не шуруповерта).

Собственно, даже в видео видно, с каким мучением они сверлят какой-то непонятный камень.
Бур на 25 и в перфоратор-то не в каждый влезет :-) Сочувствую вашему горю, ваши специфические условия требуют специфического инструмента. Именно поэтому я выделил жирным ремарку «когда в этом есть необходимость». Но если необходимость не продиктована особо прочными стенами, то не вижу смысла покупать кучу специализированных инструментов.

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

Ура, вы наконец-то с этим согласились.

Да какие там мучения? [...] или что медленно сверлит?

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

Я, знаете ли, очень ценю, что почти любая дырка в моей стене делается моим перфоратором за секунды.
А я с этим и не спорил. Не всем же так повезло как вам :-)

Если бы я каждый день делал дырочки — я бы наверно тоже это ценил. А вот раз в месяц — ничего страшного, если потребуется чуть больше времени.
А мне и раз в месяц жалко свое время и силы.
Ребята, вы, случайно, ремонтами не занимаетесь?
Пора завязывать на сегодня: сперва прочитал Postgres не стоит на месте
Невероятно кульно, а теперь сравним размеры индексов и бенчмарки с банальными «прямоугольными табличками».
Вы думаете 40 частично денормализованных таблиц и 60 индексов на них будут весить меньше, чем один нормализованный граф с 20 классами узлов? :-)
Другого ответа я и не ожидал на передовом IT-ресурсе :-)
То, что я думаю, часто не совпадает с тем, что есть на самом деле.
Приведите Ваши реальные сравнения, что сколько весит и каково время выполнения запросов в каждом случае, только после этого можно о чем-то говорить всерьез.
Я же писал, всё сильно зависит от задачи и того как её решают. Выбирайте задачу, на которой будем сравнивать :-)
Мы не хотим думать, просто дайте нам конкретные бенчмарки — конфигурация, ресурсы, скорость.
Ну ок, вот замеры, которые я проводил год назад на реальной базе: docs.google.com/spreadsheets/d/1GHwY63pOMlipNJgbRKAzXtlfa64shWagpXgdWTHiWUo/edit
У меня не стояла задача всесторонне исследовать производительность — просто показать, что оно как минимум не хуже и имеет смысл присмотреться.
Угу, вот прямо первая же метрика потрясает:

Размер на диске:
PostgreSQL: 600mb
OrientDB: 750mb
Вывод: объемы сопоставимы.

Разница в 25% — это для вас «сопоставимы».

Замеры скорости, сделанные разными инструментами — тоже доставляют.

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

Замеры скорости имеют фору у PostgreSQL ибо он напрямую общался с СУБД по бинарному протоколу, а не через JS прослойку в NodeJS.

Тестировал я на наиболее частом и сложном запросе. Вы бы не придирались :-) Если бы эти замеры доказывали неоспоримые преимущества OrientDB перед PostgreSQL по всем показателям на всех задачах, я бы пренепременно упомянул их в статье. Возьмите и проверьте на своих задачах и сделайте выводы. Сейчас же вы просто уверены, что «ничего не может быть быстрее моей любимой СУБД» и требуете от меня доказательств обратного.
25% — это во первых не такая уж большая разница.

Когда у вас размеры БД измеряются терабайтами, вы будете иначе к этому относиться.

А во вторых, там было много дубликатов связей из денормализованной SQL базы, которые графовую базу только раздували и замедляли. [...] Замеры скорости имеют фору у PostgreSQL ибо он напрямую общался с СУБД по бинарному протоколу, а не через JS прослойку в NodeJS.

Это означает, что ваше тестирование некорректно.

Тестировал я на наиболее частом и сложном запросе.

Наиболее частом и сложном для вашей системы. А в «моей» системе таких запросов нет, зато дофига объемных выборок с отбором, группировкой и агрегатами.

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

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

Это означает, что ваше тестирование некорректно.
Оно достаточно корректно для поставленной задачи.

Наиболее частом и сложном для вашей системы. А в «моей» системе таких запросов нет, зато дофига объемных выборок с отбором, группировкой и агрегатами.
Разумеется. Вы же хотели конкретный пример — вы его получили. А теперь жалуетесь, что он имеет мало чего общего с вашими задачами.

Вот еще. Я точно знаю, что есть СУБД, которые быстрее тех СУБД, которыми я пользуюсь. Заодно я знаю, благодаря чему это происходит, и что я теряю, чтобы приобрести эту скорость.
Ну раз вы всё знаете наперёд без тестирования, то мне нечего вам возразить :-)
Плюс-минус террабайт в таких масштабах погоды не делают.

Вообще-то, они денег стоят. Денег и времени.

Ну раз вы всё знаете наперёд без тестирования, то мне нечего вам возразить

Я как раз знаю на основании тестирования, по большей части.
А ещё можно зиповать данные в базе, если жёсткие диски такие дорогие :-)

Вы тестировали OrientDB на своих задачах?
Нет, не тестировал. У меня (сейчас) нет задач, требующих документо-ориентированной или графо-ориентированной БД.
25% в кровавом энторпрайсе — это, порой десятки терабайт, а то и сотни. Это, во-первых, SAN. Это резервирование в территориально-распределенных ДЦ. Это бэкапы. Это, в конце-концов, новые стойки в ДЦ. Но самое главное, это всё надо согласовать. На согласование +25% SAN уйдет больше ресурсов организации, чем на преимущества от внедрения модной СУБД.
Вы так говорите будто объёмы данных не растут просто по естественным причинам чуть ли не удваиваясь каждый год.
Речь идет о сопоставимости, а не совпадении.
25% это всегда 25%, независимо от того составляют они десятки терабайт или сотни петабайт.
А что? Для вас 25% — это несопоставимы? Это же не в 3 раза, правда? Ведь самый ценный ресурс в Enterprise это время разработчиков и время простоя системы из-за багов, так? А купить лишних винчестеров они не пожалеют денег…

тестируете вы на конкретной задаче, которая для графов выгодна

Так автор, как мне показалось, как раз стремится доказать, что таких «выгодных» — большинство.
Для вас 25% — это несопоставимы?

Для меня 25% могут иметь существенное значение при оценке.

Так автор, как мне показалось, как раз стремится доказать, что таких «выгодных» — большинство.

К сожалению, я не вижу даже попытки такого доказательства.
Да я всё жду, когда же будет клавиатура, которая будет из мозга печатать, а то мои пальцы намного медленнее мыслей :(
А вы сами-то читали статью, на которую ссылаетесь? :-)
Нонконформи́зм — стремление индивида придерживаться и отстаивать установки, мнения, результаты восприятия, поведение и так далее, прямо противоречащие тем, которые господствуют в данном обществе или группе. Часто считается синонимом понятия «негативизм» и антонимом понятия «конформизм». В некоторых случаях нонконформизмом называют просто готовность индивида отстаивать свою личную позицию в тех случаях, когда она противоречит позиции большинства. В таких случаях описанное в данной статье явление выделяют под названием «антиконформи́зм»
Вы сами-то читали, что запостили?
готовность индивида отстаивать свою личную позицию в тех случаях, когда она противоречит позиции большинства
и
человек, который не держится за свои привычки и всегда готов их поменять, если в том есть необходимость
совсем не одно и тоже. Ваше опредление больше похоже на лабильность
В данном контексте это родственные понятия. Если вам так станет легче — можете считать, что уделали меня в этом терминологическом споре :-)

На «лабильность психики» уж точно не похоже.
http://orientdbleaks.blogspot.com/2015/06/the-orientdb-issues-that-made-us-give-up.html

Хорошую базу вы для продакшена выбрали. Главное, что не пришлось над дизайном и запросами к РСУБД думать.
Скандалы, интриги, расследования… как-то много уж в той статье притянутых за уши пунктов. То форкнули проект на ГитХабе, не спросив разрешения, то удалили тег «bug» с не актуальных репортов. На тему стабильности — сам я не сталкивался с такими проблемами за тот же год, но я и не обновлял СУБД каждый месяц на последнюю версию. Тем не менее те репорты, что я создавал — довольно быстро фиксились. Я бы тоже предпочёл, чтобы багов не было вообще и всё сразу было идеально :-)

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

Серьезно? Всегда?
А разве есть контр-пример не уровня «привет мир»?
Конечно. Многие классические учетные задачи.
Приведите пример хотя бы одной, что ли.
Да легко.

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

Как мы понимаем, для РСУБД это очень простая по дизайну задача. И я что-то не вижу там ни одного, как вы выражаетесь, костыля.
Костыли начнутся, когда надо будет строить отчёты по параметрам, а параметры у всех типов ресурсов разные. Придётся либо каждый ресурс в отдельной таблице хранить, либо выносить параметры в отдельную таблицу и приджойнивать её. Это ещё одна фундаментальная проблема РСУБД, которую я забыл упомянуть.
Вот если такая ситуация случится, то можно будет смотреть, насколько костыльно такое решение. Я-то не вижу фундаментальной проблемы ни в одном, ни в другом, ни в третьем известном мне решении.
Ну ок, вот мы и нашли область применения реляционный СУБД. Довольно узкая область, надо сказать :-)
Угу, очень узкая — львиная доля всех количественных отчетов, включая чуть менее, чем все финансы.
В довольно редком приложении есть только отчёты :-)
Но отчеты очень удобно строить по реляционной БД (или по OLAP, который тоже работает по реляционной БД). А дальше либо оказывается, что вносить в нее данные тоже удобно, либо, если неудобно, на внесение данных берется другое хранилище.
Да также как и по графовой, в принципе. Индексы — не прерогатива реляционных баз.
Напомню, что изначально вы утверждали, что дизайн реляционной БД — всегда костыль на костыле. А сейчас мы дошли до того, что «ну и на графовой так сделать можно».
Кроме той маленькой области, да, костыль на костыле.
1. многие-ко-многим — костыли
2. деревья — костыли
3. большое разнообразие свойств — костыли
Без всего этого, ниша сужается до области OLAP, где опять же рулят не реляционные СУБД.
маленькой

Маленькой, серьезно?

многие-ко-многим — костыли

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

деревья — костыли

«Костыли» нужны, когда вы хотите иметь эффективные выборки по определенными видам деревьев. Это нужно не всегда. И, в общем-то, некоторые СУБД уже включают встроенную поддержку деревьев, так что тут тоже костыли пропали.

большое разнообразие свойств — костыли

Нет там никаких костылей.

ниша сужается до области OLAP, где опять же рулят не реляционные СУБД.

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

«Костыли» нужны, когда вы хотите иметь эффективные выборки по определенными видам деревьев.
Было бы странно хотеть неэффективные выборки)

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

Нет там никаких костылей.

Да ну? И как же без костылей засунуть в РСУБД гетерогенные сущности?

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

У вас есть реальные тесты, подтверждающие замедление?

Было бы странно хотеть неэффективные выборки)

Иногда конкретный вид выборок никого не волнует (его просто нет в бизнес-кейсе).

Наличие встроенной поддержки костылей не делает их более эффективными. рекурсивные запросы не избавляют от сложности log(N) каждого хопа, где N — число записей в таблице. ordpath не избавляет от обновления кучи узлов при изменении дерева.

Понимаете ли, если для меня работа с деревом прозрачна, и скорость меня устраивает — чего еще мне хотеть?

Да ну? И как же без костылей засунуть в РСУБД гетерогенные сущности?

А в чем проблема?
У вас есть реальные тесты, подтверждающие замедление?
Временная сложность алгоритмов для вас не достаточный аргумент? У каждого джойна она О(n*log(N)) при использовании индекса.

Иногда конкретный вид выборок никого не волнует (его просто нет в бизнес-кейсе).
Мы опять скатились к ограничению области применимости РСУБД: «когда плевать на эффективность выборки» или «только для небольших иерархий».

А в чем проблема?
В том, что в одной таблице могут быть лишь гомогенные сущности.
Временная сложность алгоритмов для вас не достаточный аргумент?

Нет. Когда мы начинаем говорить о конечной производительности, константы тоже имеют значение.

У каждого джойна она О(n*log(N)) при использовании индекса.

Только если стоимость прохода по индексу — O(log(N))

Мы опять скатились к ограничению области применимости РСУБД: «когда плевать на эффективность выборки»

Извините, но… нет. Сами по себе РСУБД дают очень эффективный механизм выборок.

В том, что в одной таблице могут быть лишь гомогенные сущности.

А внутри одного класса в ООП могут быть только объекты этого класса. И что?
Нет. Когда мы начинаем говорить о конечной производительности, константы тоже имеют значение.
Есть основания полагать, что константы при прямых ссылках больше?

Только если стоимость прохода по индексу — O(log(N))
А есть индексы с меньшей сложностью?

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

А внутри одного класса в ООП могут быть только объекты этого класса. И что?
То, что в ООП есть полиморфизм. А в РСУБД всё гвоздями приколочено к таблицам. И один индекс на несколько таблиц не построить, и выборка из 100 таблиц требует полного перечисления их имён и связей между ними.
Есть основания полагать, что константы при прямых ссылках больше?

Есть основания полагать, что мы ничего о них не знаем. Равно как и о цене поддержки.

А есть индексы с меньшей сложностью?

Orient же утверждает, что сделал доступ O(1) к произвольному элементу БД. Значит, ничего не мешает сделать так же организованный доступ и в РСУБД.

Не более эффективный, чем в любой другой СУБД с поддержкой индексов. Алгоритмы одни и те же.

Это утверждение работает в любую сторону.

То, что в ООП есть полиморфизм.

… создающий кучу реализационных проблем регулярно.

И один индекс на несколько таблиц не построить

Построить. Но зачем?

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

Плата за структуру.
Orient же утверждает, что сделал доступ O(1) к произвольному элементу БД. Значит, ничего не мешает сделать так же организованный доступ и в РСУБД.
Архитектура мешает. Нужно не просто id в поле хранить, но и поддерживать такие значения как linkmap, linkset, linklist.

… создающий кучу реализационных проблем регулярно.
Каких же?

Построить. Но зачем?
Как? И что значит зачем? Чтобы делать выборку по одному индексу, а не по 100.

Плата за структуру.
Полиморфизм позволяет не платить за структуру.
Нужно не просто id в поле хранить, но и поддерживать такие значения как linkmap, linkset, linklist.

Зачем? Если мы можем сделать O(1) доступ по ключу, то дальше стоимость выборки коллекции — O(n) даже в случае реализации с дополнительной таблицей.

Каких же?

Необходимость придерживаться LSP, например. Про проблему квадрата и прямоугольника слышали?

Полиморфизм позволяет не платить за структуру.

Спорный тезис. Насколько я помню, сама по себе поддержка наследования в языке приводит к (некоторым) потерям производительности.
O(1) по ключу мы можем добиться лишь потратив O(N) памяти.

К полиморфизму проблемы наследования относятся очень опосредованно.

Во первых мы про СУБД, а не про ЯП говорим. А во вторых, не все языки одинаково бесполезны.
O(1) по ключу мы можем добиться лишь потратив O(N) памяти.

Передайте это ориенту, ага?

Во первых мы про СУБД, а не про ЯП говорим. А во вторых, не все языки одинаково бесполезны.

Я, если честно, не знаю, что вы понимаете под полиморфизмом в СУБД.
Передал, говорит у него там O(n) по памяти, где n — число связей с заданным именем в заданном узле. И эта сложность не зависит от общего числа узлов в графе. В отличие от индексов.

Полиморфизм примерно в этом:

create class Cart
create class Product
create class Database extends Product
create class Framework extends Product

create property Cart linklist Product
create property Product.name string
create property Product.price decimal
create property Database.acid boolean
create property Framework.language string

create index Product.price notunique

insert into Database content { "name" : "OrientDB" , "acid" : true , price : 0 }
insert into Framework content { "name" : "NodeJS" , "language" : "javascript" , price : 0 }

select from Product where price < 1000
Передал, говорит у него там O(n) по памяти, где n — число связей с заданным именем в заданном узле. И эта сложность не зависит от общего числа узлов в графе. В отличие от индексов.

Индексы здесь вообще ни при чем — они для данной задачи не нужны, весь доступ осуществляется по основному ключу (я под индексом понимаю вторичный индекс). Так что я не очень понимаю, почему, если считать, что O(1) по ключу — достижимы, то нельзя сделать выборку коллекции за O(n), не используя никаких дополнительных типов.

Полиморфизм примерно в этом:

Вы правда не знаете, как это реализуется в реляционных СУБД? Я знаю три традиционных способа, дающих разные преимущества (и больше одного ОРМ, который сделает это незаметно для меня).

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

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

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

И вот пока я думал эту мысль, до меня внезапно дошла простая вещь, которую я почему-то пропустил раньше. Помните вот этот диалог?

Только если стоимость прохода по индексу — O(log(N))

А есть индексы с меньшей сложностью?


Так вот, индексы с меньшей сложностью есть. У хэш-таблицы амортизированная сложность доступа — O(1).
Чтобы хеш таблица работала за O(1) необходим непрерывный участок памяти объёмом O(N). И это без хеширования. С хешированием у нас появляется вероятность коллизии и тогда объём памяти нужно кратно увеличить, чтобы коллизии происходили не слишком часто. Кроме того, хеш таблицы очень дорого перестраивать для поддержки больших объёмов данных.
Чтобы хеш таблица работала за O(1) необходим непрерывный участок памяти объёмом O(N).

Не обязательно памяти. Любого хранилища.

Кроме того, хеш таблицы очень дорого перестраивать для поддержки больших объёмов данных.

А вот это вопрос констант как раз, который вы раньше проигнорировали.
Я говорил не только про оперативную память.

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

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

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

Еще раз: амортизированная алгоритмическая сложность хэш-таблицы — O(1), как на чтение, так и на добавление. Ресайз сюда включен.
Никак не обходит.

Ну да, обычно всё летает, а иногда встаёт колом на час.
Какая полезная возможность!
Еще раз: амортизированная алгоритмическая сложность хэш-таблицы — O(1), как на чтение, так и на добавление. Ресайз сюда включен.
Ну да, обычно всё летает, а иногда встаёт колом на час.
Никак не обходит.

Прекрасно, значит, и здесь у него (ориента) нет никаких концептуальных преимуществ.

Ну да, обычно всё летает, а иногда встаёт колом на час.

Scheduled maintenance рулит. Иначе вы на банальном приросте файла под БД можете очень больно лечь.
Прекрасно, значит, и здесь у него (ориента) нет никаких концептуальных преимуществ.
Есть. И я не буду больше повторять про ссылки.

Scheduled maintenance рулит. Иначе вы на банальном приросте файла под БД можете очень больно лечь.
По вашему увеличение файла происходит путём копирования содержимого из маленькой непрерывной области в большую? :-)
По вашему увеличение файла происходит путём копирования содержимого из маленькой непрерывной области в большую?

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

Явно не мне, так в Ориенте первичные ключи не в хеш-таблице хранятся, а в виде grow-only массива. А вот реляционные субд вынуждены тот или иной индекс строить с соответствующей стоимостью вставки.

Бинарные деревья куда лучше приспособлены для больших объёмов.

B-tree != бинарные деревья
А Би-деревья ещё приспособленней :-)
Но отчеты очень удобно строить по реляционной БД

Не очень удобно. Даже если забыть про избыточность собственно SQL-запроса (разработчик вынужден хранить в голове связи типа contract.id = contract_transaction.contract_id и указывать их в запросе явно, хотя до этого указывал СУБД, что contract_transaction.contract_id не может указывать может указывать только на contract.id, не забывать включать таблицу в FROM, если указал её в SELECT или WHERE), то многие часто встречающиеся для отчётов задачи решаются средствами SQL нетривиально. Например, отчёт по балансу какого-то числового агрегатного поля сущности по дням, где должен быть указан баланс на начало дня, начисления за день, списания за день, баланс на конец дня, причём баланс на начало дня должен быть ноль, даже если сущность ещё не существует, отчёт должен быть по каждой дате, даже если транзакций по сущности не было, а если транзакций не было, то начисления и списания тоже должны быть нулями. А в наличии у нас сущность и
транзакции по ней. Как минимум, придётся извращаться с преобразованием NULL в 0 и установлением начального баланса в 0.
Как минимум, придётся извращаться с преобразованием NULL в 0

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

Впрочем, я с удовольствием послушаю про СУБД, в которой это строить проще.
Бог с ним с преобразованием реальных данных, в конце концов на уровне интерфейса можно указать, что NULL отображать как 0, '', 'нет данных' или ещё как (может даже удобнее для бизнеса чем 0). Но вот start_balance + SUM(tr.amount) (где tr.amount NULL как отсутствующая в результате LEFT JOIN) или любые подобные агрегатные данные вернут тоже NULL, который так просто на уровне интерфейса не разрешить.

А я не говорил, что они есть я спорил с утверждением, что в SQL строить подобные отчёты, довольно обычные в практике, удобно. Имхо, реляционная модель вообще (а её реализация в SQL особенно) слабо приспособлена для реализации, с одной стороны, отношений типа «имеет», «содержит», «принадлежит» и т. п. между сущностями и, с другой, для агрегирующих выборок с известным начальным состоянием.

Проще это делается в, например, документо-ориентированных СУБД, в которых в качестве языка запросов используется, например, javascript — обычный reduce на коллекцию с начальным состоянием. Другое дело, что цена этой простоты меня лично не устроила и мучаюсь с Postgre- и, пока, MySql. Ещё активно навязывают (поставщики внешних решений MS SQL через начальство), но пока сопротивляюсь.
Но вот start_balance + SUM(tr.amount) (где tr.amount NULL как отсутствующая в результате LEFT JOIN)

Просто нужно вытаскивать все агрегаты отдельно, тогда можно будет разделять «транзакций за день не было» и «общий баланс транзакций за день — 0». И складывать на уровне интерфейса, благо, это просто.

(на уровне SQL тоже не сложно, прямо скажем).

Проще это делается в, например, документо-ориентированных СУБД, в которых в качестве языка запросов используется, например, javascript — обычный reduce на коллекцию с начальным состоянием.

Описываемая вами простота приходит не от документо-ориентированности — а от использования JS. Сама модель никак на это не влияет.
В этой ветке я ничего не говорил про реляционную модель, а говорил про удобство самого языка запросов. Часть неудобств проистекает из недостатков реляционной модели (многие из них с той или иной мерой успешности решаются разными производителями, как правило, по разному), а часть самим языком запросов, который создавался чтобы «любая домохозяка могла сделать запрос по базе».
А я говорил именно о реляционной БД. SQL я стараюсь избегать.
JSON убили, пора приниматься за РСУБД. Неизменно деструктивные настроения у автора =)
Для быстрого и комфортного перемещения были созданы автомашины.
Я люблю лес.
По лесу машины передвигаются плохо, а велосипеды хорошо.
Вывод: Считаю надо выкинуть все автомашины и всем пересесть на велосипеды.
погоди ховерборды
выкидывать будешь и машины и ролики и велосипед
Для быстрого перемещения были созданы суперкары.
Для комфортного — лимузины.
Но для повседневной жизни обычно выбирают хетчбэк.
Многие SQL-профи тут обычно заявляют, мол деревья и тем более графы в предметных областях почти не встречаются. Но стоит немного выйти из зоны комфорта как тут же увидишь, что любая предметная область на самом деле представляет из себя граф — набор сущностей, между которыми есть разнообразные отношения.

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

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

Что вы понимаете под «лучше»? Ну и в любом случае мне, конечно, интересно увидеть статистику, на основании которой вы делаете это утверждение.

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

Бизнес модель — коллекция сущностей с отношениями.
Графовая модель — коллекция узлов со связями.
Реляционная модель — таблицы с данными и всё.

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

Реляционная модель — таблицы с данными и всё.

На самом деле, нет. Реляционная модель — это таблицы с данными и их связи.

Первая на вторую мапится 1-в-1.

А еще бизнес-модель точно так же «точно» маппится на документо-ориентированную парадигму (потому что там тоже коллекция сущностей со связями) и на объектно-ориентированную парадигму.

Это все еще не значит, что любое из перечисленных представлений (включая реляционное) по каким-то причинам лучше подходит для реализации всех задач.
Вполне могут, почему нет?

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

Документная модель со связями — это уже графовая модель. Типа той, что мы видим в Ориенте.

В таблицах нету связей.

Это экзистенциальный вопрос. В таблице есть информация, позволяющая однозначно определить связанный объект. Этого достаточно.

Документная модель со связями — это уже графовая модель.

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

Вы так говорите, будто в других БД «физически» хранятся не «числа» (опустим для простоты тот факт, что идентификатором записи может быть что угодно). Те же самые числа, пусть даже в OrientDB они являются указателями на конкретное физическое место в БД.

Семантику этих «чисел» обеспечивают метаданные, лежащие поверх, и ограничивающие операции. Сейчас, наверное, все РСУБД поддерживают внешние ключи, как для ограничения множества допустимых значений, так и для распространения изменений. Семантически это эквивалентно ссылкам на объекты.

Вы можете к возрасту приджойнить айдишники и получить странный результат. А РСУБД ничего на это даже не возразит.

Да, могу — ни одна известная мне РСУБД не имеет ограничений на объекты под джойнами. Но есть и оборотная сторона — я могу приджойнить возраст к возрасту, или имя к имени, или результат группировки к результату группировки. Можно ли так сделать в графовой БД?

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

Можно, через подзапросы.
Можно, через подзапросы.

Во-первых, являются ли «подзапросы» свойством любой графовой БД?
Во-вторых, какова их функциональность и эффективность по сравнению с РСУБД?
1. Я не говорю про любую ГСУБД. Но в любой толковой — можно. Из толковых я знаю только одну.

2. Да такая же при наличии индексов. Разве что для full outer join нужно шаманить.
Я не говорю про любую ГСУБД. Но в любой толковой — можно. Из толковых я знаю только одну.

Значит, это не врожденное свойство графовых БД.

Да такая же при наличии индексов. Разве что для full outer join нужно шаманить.

Правда?

У меня есть две таблицы (два класса в терминах ориента), «книги» и «фильмы». В каждой из них есть поле «год». Мне нужно получить таблицу вида «год выхода — число книг — число фильмов». Считаем, что с каждой стороны есть хотя бы по одной записи для каждого года, поэтому достаточно INNER JOIN.
Разумеется, не все ГСУБД одинаково полезны :-)

Если честно, лень шаманить с селектами… в ГСУБД эта задача решается несколько иначе и более эффективно:

select value , book.length() as booksCount , movies.lengh() as moviesCount from Year


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

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

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

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

3. Я бы не назвал это таким уж прям костылём. Если у нас выводится аналитика по годам, то без сущности «год выпуска» так или иначе не обойтись. К ней надо будет привязывать не только вышедшие произведения, но и ежегодные премии, аналитические статьи и тп. А не вытягивать их по косвенным данным (датам во всех этих сущностях) при каждом запросе, внимательно следя, чтобы диапазоны не пересекались. Тем более что премия за текущий год может вручаться в следующем. А аналитическая статья за любой год может выйти хоть через десятилетие.

4. Можно ссылку, где обсуждали?
Это в РСУБД переход по связи дорогой. Тут же это почти ничего не стоит (прочитать лишний блок памяти, который, к тому же, скорее всего возьмётся из кэша).

Это все равно дополнительная операция. А кэши — они во всех СУБД есть.

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

Вот и увеличение стоимости поддержки.

Если у нас выводится аналитика по годам, то без сущности «год выпуска» так или иначе не обойтись.

Год выпуска — это не сущность, а атрибут.

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

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

Можно ссылку, где обсуждали?

habrahabr.ru/post/246313
habrahabr.ru/post/245241

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

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

Год выпуска — это не сущность, а атрибут.
Ссылка на сущность хранится в атрибуте. Это философский спор :-) Я лично усматриваю в годе выпуска все признаки сущности. Сформулировать их пока не возьмусь, чисто интуитивно.

Все эти проблемы решаются введением соответствующего атрибута, сущность все еще не нужна.
Но с ней в целом удобней.

habrahabr.ru/post/246313
habrahabr.ru/post/245241
Спасибо, почитаю.
Она как минимум лучше масштабируется, чем джойны таблиц.

Почему?

Один раз пишется обобщённый код и всё.

А создает описание связей в БД тоже «обобщенный код»?

Я лично усматриваю в годе выпуска все признаки сущности.

Попробуйте сформулировать, и поймете, что по этим признакам всё — сущность. Это, конечно, нативный для графа подход (все есть вершина кроме того, что ребро), но вы уверены, что вам будет удобно так работать.

Но с ней в целом удобней.

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

А создает описание связей в БД тоже «обобщенный код»?
Вполне, почему бы и нет?

вы уверены, что вам будет удобно так работать.
Да, весьма.

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

Уже проходили: для реляционной БД это тоже возможно.

Вполне, почему бы и нет?

Ну так, представляю себе результаты его работы.

Да, весьма.

Пробовали? Пока все ваши примеры — они документо-ориентированы.

В бизнесе есть «отчётные периоды» и это вполне себе бизнес сущности.

Не надо путать отчетные периоды и год выхода. Это очень разные вещи. А временные метки вы себе вообще сам придумали, я про них не слова не сказал.
Уже проходили: для реляционной БД это тоже возможно.
Если б всё было так легко, никто бы не пилил NoSQL решения.

Ну так, представляю себе результаты его работы.
Озвучите?

Пробовали? Пока все ваши примеры — они документо-ориентированы.
Бизнес вообще документно ориентирован.

Не надо путать отчетные периоды и год выхода.
Вы строите отчёты по годам. Вполне себе отчётные периоды.
Если б всё было так легко, никто бы не пилил NoSQL решения.

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

Озвучите?

Если вкратце, то: book.Editor_Person.

Бизнес вообще документно ориентирован.

Ну и как же вы собираетесь его положить на чистый граф тогда?

Вы строите отчёты по годам. Вполне себе отчётные периоды.

Нет, я строю отчеты по атрибуту «год выхода». Это не то же самое, что «отчетный период — 2010 год» или «финансовый год 2010».
А вы думаете, NoSQL решения «пилят» из-за невозможности сделать константное время доступа по ключу?
Из-за фундаментальных проблем масштабирования РСУБД.

Если вкратце, то: book.Editor_Person.
Что это?

Ну и как же вы собираетесь его положить на чистый граф тогда?
Бизнес документы тоже имеют перекрёстные ссылки.

Нет, я строю отчеты по атрибуту «год выхода». Это не то же самое, что «отчетный период — 2010 год» или «финансовый год 2010».
Не вижу разницы.
Из-за фундаментальных проблем масштабирования РСУБД.

Как интересно! А расскажите какие там есть проблемы? И да кстати посмотрите про то как PostgreSQL ускоряют при помощи GPGPU.

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

Это типичный пример именования, вышедшего из под обобщенного кода.

Бизнес документы тоже имеют перекрёстные ссылки.

Перекрестные ссылки — это, конечно, граф, но бизнес-документы — это не чистый граф, а речь выше шла именно об этом.

Не вижу разницы.

Я, в принципе, уже заметил.

Окей, представьте, что у вас не год, а дата — и вам надо строить аналитику по датам (рождения, смерти, свадьбы и развода).
Это типичный пример именования, вышедшего из под обобщенного кода.
Зачем тип указывать в имени свойства?

Перекрестные ссылки — это, конечно, граф, но бизнес-документы — это не чистый граф, а речь выше шла именно об этом.
Что такое «грязный граф»?

Окей, представьте, что у вас не год, а дата — и вам надо строить аналитику по датам (рождения, смерти, свадьбы и развода).
Точно так же, создаём отдельные узлы для дат и имеем быструю аналитику по ним. Говорю же, принципы работы с графами несколько отличаются от подходов к которым вы привыкли при работе с таблицами.
Зачем тип указывать в имени свойства?

Потому что обобщенный код так сгенерил.

Что такое «грязный граф»?

Граф, в котором у вершин есть свойства.

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

Вы себе представляете количество таких вершин?

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

Спасибо, я в курсе. Только почему-то подходы, применяемые в реляционной модели, вы считаете костылями, а подходы, применяемые в графовой — нет.
Потому что обобщенный код так сгенерил.
Напишите нормальный обобщённый код :-)

Граф, в котором у вершин есть свойства.
Теория графов не накладывает никаких ограничений на вершины.

Вы себе представляете количество таких вершин?
Не больше чем узлов в индексе.

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

Если бы можно было написать нормальный обобщенный код, порождающий модель, соответствующую домену, программистов можно было бы выкинуть на свалку.

Теория графов не накладывает никаких ограничений на вершины.

И как следствие никак не описывает алгоритмы для работы с «дополнительными» данными.

Не больше чем узлов в индексе.

Вот только узлы в индексе я — как разработчик — не вижу. А вершины в граф добавлять мне.

Потому что они имеют большую алгоритмическую сложность

Докажите.

меньшую наглядность.

А это субъективно.
Если бы можно было написать нормальный обобщенный код, порождающий модель, соответствующую домену, программистов можно было бы выкинуть на свалку.
Вы улетели в стратосферу. Что мешает генерировать нормальные имена в духе «book.editor»?

И как следствие никак не описывает алгоритмы для работы с «дополнительными» данными.
А должна? К чему вы клоните?

Вот только узлы в индексе я — как разработчик — не вижу. А вершины в граф добавлять мне.
Вы их фактически создаёте налету в агрегирующем запросе. Из таблиц «инфа о книгах» и «инфа о фильмах» создаёте виртуальную таблицу «инфа о годе выпуска».
Бизнес вообще документно ориентирован.

Бизнес обычно не документно ориентирован, документы, как правило, лишь средства отражения (учёта) состояния бизнес-процессов, модель по сути, по которой кто-то может узнать состояние бизнес-процессов на определенный момент времени (при условии, что документы составлялись в нужном объёме и фиксировали объективные состояния процессов).
Бизнес — разный. Учетный бизнес вполне бывает документо-ориентирован.
В подавляющем большинстве бизнесов учёт не самоцель, а средство контроля.
Видимо, я имел дело с подавляемым меньшинством.
Видимо, вам повезло иметь дело с бизнесом, обслуживающим задачи учёта других бизнесов, государства, частных лиц и т. п.
Это просто игра слов, что вы так серьёзно-то :-)
Что мешает генерировать нормальные имена в духе «book.editor»?

Каждый раз что-нибудь новое.

А должна? К чему вы клоните?

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

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

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

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


Documents are the main concept in document databases. [...] These documents are self-describing, hierarchical tree data structures which can consist of maps, collections, and scalar values. The documents stored are similar to each other but do not have to be exactly the same.


каким образом модель данных «граф» может работать?

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

И что хорошего в том, чтобы создавать её при каждом запросе отчёта?

Отсутствие дублирования данных, например. Ну и вообще семантическая стройность.
Сформулировать их пока не возьмусь, чисто интуитивно.

Какой-то конкретный год — объективно существующая сущность, период реального физического времени между двумя (пускай и субъективно выбранными) событиями. Год издания книги — это отношение сущности «книга» к сущности «год» по признаку того, что событие «издание» произошло в данный конкретный период времени. Это не свойство книги, не её наполнение, это её отношение к внешнему миру, такое же, как, например, «страна издания».
И вам читать про Партриджевскую парадигму «любое свойство есть отношение».
Разницы между отношениями «в книге 500 страниц (книга состоит из 500 страниц)» и «книга издана в 2015 году (книга издана во время течения 2015 года» не чувствуете?
Если я вдруг начал мыслить терминами «книга издана в 2015 году — это отношение „год издания“ между сущностями „книга“ и „год“», то я могу с успехом распространить это мышление на страницы, причем как минимум двумя способами.

(а) «книга» относится к классу «500 страниц»
(б) «книга» содержит 500 связей со страницами
Второй вариант вполне встречается на практике )
На практике встречается почти что угодно, вопрос частоты и удобства применения.
На практике для генерации отчётов с ежедневной разбивкой по данным, имеющим частью естественного первичного ключа (реально используется суррогатный первичный ключ) датувремя я использую предгенерированную табличку из одного столбца report_date типа дата. Это результат анализа воможности получить нужный отчёт (с учетом денормализации) за время меньше минуты и пересчитать всю денормализацию на момент старта транзакции меньще чем за час на доступных ресурсах в пределах 4-х SQL-СУБД.
Не нашёл там упоминаний Партриджа.
Семантику этих «чисел» обеспечивают метаданные, лежащие поверх, и ограничивающие операции. Сейчас, наверное, все РСУБД поддерживают внешние ключи, как для ограничения множества допустимых значений, так и для распространения изменений. Семантически это эквивалентно ссылкам на объекты.

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

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

А с другой стороны… я правильно понимаю, что вы хотите чего-то навроде «есть таблицы Books и Authors, я хочу, чтобы когда я пишу SELECT * FROM Books, Authors, система автоматически строила джойн»? Или чего-то другого?
Нет, это именно ограничение парадигмы, реляционной модели — в ней нет такой сущности как «связь или зависимость между кортежами (строками) отношений (таблиц)», а есть лишь независимые кортежи независимых отношений и операции над ними. Чисто теоретически типы атрибутов не ограничены примитивными типами и могут быть другими кортежами, но на практике атрибуты — примитивные значения, которые иногда используются разработчиком для ссылки на другие отношения.

В идеале вообще что-то вроде: SELECT Books.Title, Books.Authors.Name; добавляя нынешние FROM и JOIN лишь в случае необходимости изменения основного поведения.
В идеале вообще что-то вроде: SELECT Books.Title, Books.Authors.Name; добавляя нынешние FROM и JOIN лишь в случае необходимости изменения основного поведения.

Угу. Как ни странно, добрая половина ORM дает вам именно такое поведение, все еще имея внутри реляционный код. И для этого используются тривиальные метаданные. Причем, что характерно, O и M из ORM для этого не нужны, достаточно метаданных и конструктора запросов.
Ну так наличие таких инструментов как раз и говорит о том, что популярные реляционные СУБД не очень удобны в ежедневном использовании без подобных обёрток, зачастую скрывающих реляционную модель хранилища.
Не «популярные реляционные БД», а «используемый язык запросов».
Формально вы правы, на практике для популярных реляционных СУБД язык запросов означает SQL.
Просто язык — это еще не парадигма. Точно так же, как не все описанные в посте особенности ориента надо переносить на графовые БД, так и не все проблемы SQL надо переносить на реляционные БД.

В DB/2, кстати, весьма зачетный внутренний язык был.
«Границы моего языка есть границы моего мира» (Л. Виттгенштейн).
http://www.psychologos.ru/articles/view/piraha
Вот поэтому разработчик должен быть полиглотом.
Повторюсь: формально вы правы. Я ещё 20+ лет назад писал запросы к реляционным БД на Сях без всяких намеков на SQL, чисто в терминах реляционной алгебры плюс хэндлеры. Но мэйнстрим таков, что РСУБД = SQL СУБД, как бы мы к этому не относились.
Возможно, тогда надо прыгать в сторону развития языка, а не только отказа от РСУБД?
Примерно так и есть в OrientDB с той лишь разницей, что он автоматически не «уплощает» коллекции. То есть селект вида:

SELECT title , authors.name , authors.muses.name FROM Book

Вернёт записи вида:

( "Hello" , [ "John" , "Artur" ] , [ [] , [ "Elena" ] ] ] )

Так завлекательно описываете, что хочется попробовать :)
Сейчас меня тут, думаю, закидают помидорами, но поделюсь собственным впечатлением.

Программирую я давно — с самой школы. Так как начинал что-то писать более-менее серьезное в Delphi, то понятия ООП «впитал с малолетства». А так как задачки были ерундовые, с СУБД тогда дела не имел.

Поиметь дело с ними пришлось несколько лет назад, когда тяжелая судьба занесла меня в Java Enterprise. Зная неплохо Java (а до нее мея опыт в C# и C++), я впервые столкнуля с тем, что такое реляционная база данных. А еще что такое ORM Hibernate. Влетел, можно сказать, обеими ногами и увяз по колено.

И вот, что я могу сказать о своих первых впечатлениях (которые потом, по мере использования, только укрепились).

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

Долгое время я мирился с когнитивным диссонансом, выслушивая со стороны старших товарищей аргументы в духе «таблицы проще хранить, с ними быстрее работать» и т. д… Я просто пожимал плечами и верил, что они правы. А сейчас вижу, что и этот оплот разваливается (если верить статье). Надо попробовать попользоваться хоть немного этой самой OrientDB при случае. Жаль, что теперешняя моя работа от СУБД далека диаметрально.
А вы не верьте статье. Никуда РСУБД не разваливаются, просто для ряда задач они менее эффективны, чем другие хранилища. Пять-десять-пятнадцать лет назад доля таких задач была меньше (и выбор был меньше), сейчас она смещается (с повышением разнообразия и развитием альтернативных парадигм хранения).
Пять-десять-пятнадцать лет назад доля таких задач была меньше

В том-то и дело, что я такими задачами почти не занимался. Мне было интересно «использовать ООП наполную катушку».

Я прекрасно понимаю, что для задач типа складских «сводная таблица цена-количество-стоимость» табличное представление — самое верное и простое. Понятно, что таблицы хороши для представления однородных данных…

Но эти задачи давно уже все решены. Сейчас действительно актуальны Wiki и соцсети. Как то, так и другое редставляется жутко нерациональным, если организовывать данные в виде таблиц. Как составить графовую модель сети Facebook, я, думаю, с точностью незначительных нюансов, нарисую за полчаса. А вот как эти данные уложить в табицы… Тут без поллитры точно не разберешься. А если редставить себе, что будет использоваться еще и ORM, то вообще кирдык психике (видел я сложность Hibernate-овских запросов на сравнительно примитивной задаче).

Мне кажется, что основная причина, по которой все до сих пор держатся за реляционщину — страх перед ошибками. Вот если мне скажут «мы используем Oracle, потому что его 20 лет писали и чинили, а твою <вставьте слово> я впервые вижу», то я это вполне пойму. А +25% к размеру базы — это не цена за простую понятную и легко масштабируемую программу, как мне кажется.
В том-то и дело, что я такими задачами почти не занимался. Мне было интересно «использовать ООП наполную катушку».

Понимаете, это заведомо неправильный подход. «Интересно» — решать конкретную прикладную задачу, выбрав для нее тот инструмент, который для нее подходит. Это не всегда ООП, это не всегда РСУБД, это не всегда <что угодно другое>.

Я вот сейчас для себя пилю проектик, в котором три года назад использовал бы РСУБД (MS SQL), год назад — документо-ориентированную БД (RavenDB), а сейчас, в итоге, взял хранилище событий (EventStore), а по мере увеличения нагрузки планирую добавлять read models на том, на чем будет оправданнее.

Я прекрасно понимаю, что для задач типа складских «сводная таблица цена-количество-стоимость» табличное представление — самое верное и простое. Понятно, что таблицы хороши для представления однородных данных… Но эти задачи давно уже все решены.

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

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

Основная причина — это непонимание, как работают «новые» (на самом деле, нет) БД, нежелание разбираться, и нежелание искать выгодные стороны (я, конечно, говорю о новых проектах, с унаследованным ПО все веселее). Но я вот знаю одну (весьма авангардную) разработческую компанию, которая между мажорными версиями своего ПО сменила используемую СУБД с RavenDB (документо-ориентированная) на MS SQL (РСУБД) — просто потому, что их не удовлетворял опыт работы с Raven.
Ну, надо сказать, что сменили они его с появлением Column Store Index, добавившего новых не очень реляционных возможностей.
Откуда дровишки? «Они» поддерживают MS SQL Server начиная от 2005.
Как составить графовую модель сети Facebook, я, думаю, с точностью незначительных нюансов, нарисую за полчаса.

Кстати, у ФБ — мультипарадигменная модель, там есть и графы, и документо-ориентированные куски. И это если не учитывать внутреннюю кухню, которую мы не видим.

Я, естественно, о бизнесе, а не о том, что они реализовали.
Не надо передёргивать про ORM, на питоне укладка вашей задачи в таблицы займет у меня ~ пол часа, так что всё с ними хорошо.
Укладка-то да. А вот понимание внутреннего устройства, отладка глюков «укладчика» и т д… ORM как всякая «умная автозабивалка» хорош ровно до тех пор, пока в него не приходится влезть, чтобы понять, где и почему он накосячил.
Обычно разобраться и починить глюк ORM в разы проще, чем смигрировать БД, особенно на БД с другой парадигмой.
Лично я прекрасно чувствую себя внутри кода тех орм что использую.
У самого не малый опыт в базах данных. Тоже возникали подобные мысли о не совершенстве реляцилнных баз. Но есть непреодалимое «но». Называется оно «уровень абстракции». Наверное знаете про трех-звенную архитектуру построения. Вот в этой архитектуре, во второем слое (бизнес-логики) имеет место применять понятие сущьностей. Именно там их и удобнее всего принимать от клиента как сущьности и конверитровать в плоскую модель. И из плоской модели выдавать клиенту уже собранные сущьности.

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

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

В моей реализации бизнес сущности везде — и на клиенте, и на сервере, и в базе данных. И это, скажу я вам, крайне удобно и не слабо повышает эффективность трудозатрат. К тому же ещё сервер и клиент работают через один и тот же полиморфный js-api:

// передать управление салоном пользователю с id "cool-manager"
salon.Manager().set( [ 'cool-manager' ] , [ myPerson ] ).then( managers => {
    console.log( managers.map( String )
} )


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

Так в чем же выигрыш?

Перевод в js-api для меня не делает погоды. Есть только один единственный модуль, который знаком с этой технологией — для обмена данных от внешнего клиента, чтоб переколбасить эти все данные во внутрениий, опримизированный и построеный для системы api и сформировать правильное сообщение в систему. Все. И то, если у клиентов совершенно другая система обмена сообщений (напрмер описанная на хабре HL7), то и этот модулек не будет использоваться.

Так подведем маленький итог нашей дискуссии: Сущности важны в основном процессе. Если у вас обработка(бизнес-логика) крутится непосретственно в базе — то тогда есть удобство использовать сущности. Иначе, любые конечные ветви взаимодествия извне полюбому упирается в плоскую передачу упорядоченных байтов, будь то обмен даххы наприме по tcp, хранение в бинарном файле или в РСУБД.
У вас какие-то не правильные работодатели :-) В норме, бизнесу нужно как можно быстрее, потом как можно больше, потом как можно стабильней. Это не значит, что клиенту пойдёт ничего не умеющее падающее приложение. Это значит, что пощупать и внести коррективы можно будет как можно раньше, а не в последний день. Ну и лёгкая недоделанность во многих областях вполне допустима — многочисленные «вечные беты» тому пример.

Все-то, конечно всё понимают, да только получается как в известном анекдоте: https://hsto.org/files/8bb/23b/a3a/8bb23ba3aede496395ac3a63d42380f2.jpg
:D работодатели даже очень правильные. Немецкая компания выкупленная американцами. Так что они знают толк в производстве.
Зная неплохо Java (а до нее мея опыт в C# и C++), я впервые столкнуля с тем, что такое реляционная база данных. А еще что такое ORM Hibernate. Влетел, можно сказать, обеими ногами и увяз по колено.

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

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

Вот я, давеча, раскритиковал C++. Я его более-менее знаю, но совсем не люблю. Что там началось…

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

Smashing Magazine


не во что :)

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

— есть задачи, с которыми реляционные БД справятся лучше. Автор же предлагает использовать одну БД везде и всюду, судя по комментарию:
Возвращаться на реляционные — боже упаси

— и вот эта цитата:
Нет, я не буду рассказывать вам про MongoDB или ещё какую неполноценную «убийцу SQL».

Я расскажу вам про другого «убийцу SQL».
Какое у вас восхтительное умение читать между строк.

Я в этой фразе:
Возвращаться на реляционные — боже упаси

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

Я расскажу вам про другого «убийцу SQL».

Юмор у всех разный. Один пошутил, другой не понял…
Где он что-то писал типа «не используйте реляционные базы НИКОГДА»?

В заголовке
Почему вы не используете швейцарский нож для повседневного приема пищи?
Потому же почему вы не пользуетесь всеми этими приборами для повседневного приёма пищи:



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

Я расскажу вам про другого «убийцу SQL».
Про полноценную убийцу SQL.
UFO just landed and posted this here
Они не удовлетворяют требованиям ACID (Атомарность, Согласованность, Изолированность, Надёжность). OrientDB этим требованиям удовлетворяет.


Обоснуйте по каждому пункту, пожалуйста. Желательно с примерами.
Отличное чтиво.

Не прочитал и страницы, как наткнулся на раздел:
Breaking of ACID properties when using remote protocol and Commands (SQL, Gremlin, JS, etc)


Т.е., как и монга «в целом ACID, но иногда не ACID»

Про «Durability», авторы, похоже, не совсем понимают, что это вообще означает, т.е. цитату из wikipedia они приводят, конечно, но смысла её не понимают, судя по следующей цитате:

If you're using an OrientDB Server connected remotely, if your application crashes the engine continue to work, but any pending transaction owned by the client will be rolled back.
Там транзакции хранятся на клиенте, да. Так что при падении этого клиента транзакции, очевидно, отменяются. Не очень понял, чем это не соответствует ACID, но монга вообще транзакции не умеет.
Приятно, что монга не умеет чего-то, что вроде как умеет ориент.

Ваша цитата, к какой части моего комментария относится?
К обеим, они же об одном и том же вроде как :-)
Отнюдь. Durability — это не про автоматический откат транзакций.
Это про то, что если транзакция прошла, то она никуда не денется. И в конце даётся капитанская ремарка, что если транзакция не успела пройти и произошёл сбой приложения, то и незавершённая транзакция будет потеряна.
В оригинальной цитате имеется в виду фейл сервера БД, а не приложения. Что произойдёт с закоммиченной транзакцией на сервере OrientDB при обрубании источника питания?
О какой цитате идёт речь?
Ничего не произойдёт. Это ж acid субд.
Транзакции на клиенте? ACID хранилище? АХАХАХАХАХА
До коммита они хранятся на клиенте.
Иии? Вот дальше пошла передача на сервер, в середине этого действа происходит обрыв связи. Что наблюдаем на сервере?
Ничего. Транзакция посылается единым пакетом.
Следующий вопрос. Пока идет проводка транзакции на сервере, и я в этот момент запрашиваю эти данные, что я увижу?
… особенно с учетом репликации.
А что вы ожидаете увидеть?
А почему вы отвечаете вопросом на вопрос? :) Причем тут что я ожидаю увидеть. Вопрос состоит что будет на сервере. Если на сервере эти данные пишутся транзакционно, то зачем транзакции на клиенте?
А почему вы спрашиваете? Чтобы не напрягать сервер тем, что возможно и не надо будет коммитить.
Некоторые, особо «передовые» программисты, предлагают хранить каждый тип моделей в своей СУБД. «Важные данные» в реляционных, деревья в графовых, а примитивные вообще в словарях. Но подобные подходы вида «всякой задаче свой инструмент» лишь добавляют головной боли (и как следствие багов разной степени тяжести) на тему консистентности данных в разных частях приложения.


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

«Упаси вас Бог от общения с людьми, которые не предлагают аргументов, а сыплют не подтверждёнными цитатами слабо известных им людей» (с) Цицерон
«Главная проблема цитат в интернете в том, что люди сразу верят в их подлинность» В.И. Ленин
Еще один не осилил SQL?
Автор, а вы знаете, что для реляционных СУБД есть стройная реляционная алгебра? То есть корректность построений можно проверить математически.
Можно ли проверить корректность вашей модели?
Или «мамой клянус, правильно работает!»
Автор упомянул её в первом жа абзаце. И часто вы пишете комментарии прочитав лишь один заголовок? :-)

Можно пример этой «математической проверки корректности»?
Вы не сравнивали с ArangoDB? Там тоже графы, джойны и транзакции.
Вот если бы не джойны, а прямые ссылки и с гибридной схемой — было бы супер.
Хм. Любопытно. А как, бишь, Orient (да и другие графовые БД) обеспечивает двустороннее прохождение по связи за одинаковое время и одинаковыми запросами?
И сколько это стоит CPU, RAM и HDD… То на некоторых задачах предпосчитанные join'ы в какой-нибудь кассандре прекрасно работают, хотя памяти и понимания структуры данных требуют чуток побольше.
Оба узла хранят ссылки друг на друга.
Дублирование данных со всеми вытекающими отсюда развлечениями.
Как всегда компромисс между скоростью и потреблением памяти :-)
Вам не кажется, что после этого ваши упреки РСУБД в «дублировании данных» и «O(n) на хэш-таблицу» несколько надуманны?
Вы так говорите будто индексы ничего не весят.
Нет, я так говорю, как будто индексы — это очередной компромис между скоростью и потоеблением памяти.
Основная моя претензия к NoSQL СУБД это одна единственная вещь. Как по ней строить аналитику? Вот по РСУБД весьма просто, а как приходим в NoSQL то начинаются танцы с бубном.
Вот именно поэтому NoSQL чаще рассматривают в контексте polyglot persistence. Но в принципе, теми же инструментами можно и на самой nosql базе построить хранилище под отчеты.
Но в принципе, теми же инструментами можно и на самой nosql базе построить хранилище под отчеты.

Угу и каждый раз свое.
Ну да. В паре случаев это даже будет удобнее.

Не, я не рекомендую так всегда делать, я просто говорю, что у этого конкретного недостатка есть механизмы компенсации.
Проблема как раз в том что в паре случаев :) А обычно NoSQL используют из-за NoSQL is WebScale!
Ну, если мозга нет, то о любую технологию можно сломать что угодно.
А в чём сложности с NoSQL?
В том что аналитику вы по этим данным можете построить с трудом и каждый раз придется писать код.
Мне кажется вы неправомерно экстраполируете свой опыт работы с некоторыми NoSQL решениями на все нереляционные СУБД.
Я пока не видел ни одной NoSQL СУБД где это не требовалось. Да у части есть SQL подобный язык для аналитики, но как правило его возможности весьма слабы и что-то сложное из него не получить.
Приведите примеры, не будьте голословными.
Примеры чего? Я вам тоже могу предложить подтвердить что я там неправомерно экстраполирую.
create property Person.friend linkset Person
Я где то вычитал, что если переместить документ на который ссылаются через link*, то эта связь ломается. А если в документ добавлять данных и он выйдет за пределы первоначально ему отведенные, то этот документ подлежит перемещению (из mongodb).
Т.е. мы либо не можем расширять документы, либо ломаются связи.
Так ли это, как это «обруливается»?

Или забыть про link* и использовать edge?
The record never loses its identity unless it is deleted. Once deleted its identity is never recycled (but with «local» storage). You can access a record directly by its RecordID. For this reason you don't need to create a field as a primary key like in a Relational DBMS.

http://orientdb.com/docs/2.1/Concepts.html#recordid

Как обруливается точно не знаю, но предполагаю, что так: в файлах *.cpl хранятся собственно данные, которые могут менять своё положение при изменении размеров, а в файлах *.cpm — маппинг идентификаторов на смещения в cpl-файлах. То есть да, получается некоторый индекс с O(1) по идентификаторам (массив со смещениями). И нет, это не то же самое, что первичный ключ в РСУБД и той же Монге, где значение этого ключа можно указывать своё, а не строго автоинкремент, из-за чего вместо массива приходится использовать более сложные структуры данных, допускающие пропуски.
Сделал тест «на коленке», 100к user(name, parent), база маленькая — долго ждать неохота, заливалось в 4 раз медленнее чем в mongo, но это не важно.
Цель — протестировать скорость ссылок «select name, parent.name from User», 100 запросов по 100 документов в каждом + в каждом документе ссылка на родителя, в случае с монгой — родители достаются последующим запросом:
OrientDB: ~1.4 сек
MongoDB: ~0.09 сек

Если из OrientDB выбирать без ссылок «select name from User», то выходит ~1.2 сек, возможно ссылки «быстрые», но общей картине это не помогает — OrientDB сам по себе медленный.

Т.е. если я буду делать join через ключи в монге, то все равно выходит быстрее чем через ссылки в OrientDB. Большие объемы в этом тесте не помогут OrientDB, т.к. используется SB-Tree для выборки.

Возможно (сложные) графы оправдали бы OrientDB, но они мне не часто встречаются, те что встречаются обычно решаются «в лоб» (иногда даже без джойнов).
«На коленке» можно легко и противоположных результатов добиться :-) Например, MongoDB по умолчанию не дожидается записи в журнал, чтобы ответить «спокойно, я всё сохранила». В купе с отсутствием транзакций, вы легко можете потерять консистентность данных при падении субд. Если настроить, чтобы она отвечала лишь после сброса журнала на диск, то монга тут же становится в два раза медленнее на инсертах, чем ориент. Про селекты — нужны подробности как вы делали «100 запросов по 100 документов». Судя по такой большой разнице, подозреваю, что к монге обращались через курсор, а к ориенту — через 100 запросов да ещё и со смещением.

Покажите свой код. Вот мой: https://github.com/nin-jin/dbench

By default, all write operations will wait for acknowledgment by the server, as the default write concern is WriteConcern.ACKNOWLEDGED.
Write operations that use this write concern will wait for acknowledgement from the primary server before returning. Exceptions are raised for network issues, and server errors.
Acknowledged write concern does not confirm that the write operation has persisted to the disk system.
With a journaled write concern, the MongoDB acknowledges the write operation only after committing the data to the journal. This write concern ensures that MongoDB can recover the data following a shutdown or power interruption.

http://docs.mongodb.org/manual/core/write-concern/
Да, согласен. С fsync журнала, да ещё и при одиночных записях тормозить будет. Тогда стоит сравнивать с batch insert'ами, т. к. journaled ждёт ближайшего fsync'а журнала, и, если сама запись пройдёт быстро, то это просто тупое ожидание следующего тика таймера. По умолчанию 100 ms, если журнал и основная база лежат на одном диске, что много больше стандартного insert'а.
Например, MongoDB по умолчанию не дожидается записи в журнал, чтобы ответить «спокойно, я всё сохранила».
Это не влияет на скорость записи в бд, влияет на скрипт, будет он ждать или нет ответа и скорость отправки последовательных операций.
Для проверки OrientDB я запускал 10 потоков, OrientDB кушал ~95% cpu, т.е. выдавал все что мог, поэтому ожидание в скрипте не влияло.
В купе с отсутствием транзакций
Да, транзакции — серьезный фактор, поэтому ArangoDB стоит в списке на рассмотрение.

Вот кусок кода, для OrientDB один запрос без смещения, на поле name сделан индекс SB-Tree, без индекса работает в 400 раз медленнее — т.е. индекс работает.

Тесты запускал в 1 поток, сейчас запустил в 10 потоков (итого 1000 запросов по 100 документов):
OrientDB: ~7.3 сек
MongoDB: ~0.4 сек
будет он ждать или нет ответа и скорость отправки последовательных операций.
Запись без ожидания ответа, не считая последнего документа, который ждет ответа записи, что означает что запись завершена.
Это не влияет на скорость записи в бд, влияет на скрипт, будет он ждать или нет ответа и скорость отправки последовательных операций.
Ну да, это влияет на бенчмарки :-)

parents = db.user.find({'_id': {'$in': list(parents)}})

Я так понимаю тут возвращается курсор и нужно развернуть его в список:

parents = list(db.user.find({'_id': {'$in': list(parents)}}))

Что показывает explain?
100 запросов вы делаете разные или одинаковые?
Я так понимаю тут возвращается курсор и нужно развернуть его в список:
Упс, пропустил, в первой версии был пербор в цикле, поправил (стало медленнее в 2 раза ~0.18 сек), сделал новый набор данных — увеличил кол-во родителей:
OrientDB: ~1.7 сек
MongoDB: ~0.4 сек

Завернул тест в docker для тех кто хочет попробовать у себя, запускать так:
git clone https://github.com/lega911/db_test0
cd db_test0
./init.sh
./fill.sh
./start.sh

Для запуска нужен docker и github, если порты 2424, 2480, 27020 уже заняты, их можно сменить в init.sh либо вырезать совсем, кол-во документов можно сменить в fill.sh
Запустил тест на Digital Ocean (20$), в один поток и в 10:
OrientDB: ~6 сек и ~18 сек
MongoDB: ~1.3 сек и ~3.8 сек

Запустил на 1М документов, если курсоры не отвалятся то выложу результат.
Перемерял 100k на серверах Амстердама и Нью Йорка с отключением конкурирующего контейнера:
100k
mongodb: 0.6s, 3s
orientdb: 4s, 16s

1M
mongodb: 0.9s, 3.5s
orientdb: 5s, 18s

Да, похоже выборки по индексам в несколько раз медленнее. Я обновил свои тесты (https://github.com/nin-jin/dbench) — теперь они тоже заводятся из под докера. На 100К записей у меня получилась выборка по индексам у ориента в 2 раза медленнее, чем в монге и постгресе, а выборка связанных записей в постгресе в 2 раза быстрей, чем в монге и ориенте. Потом проверю динамику изменения скорости в зависимости от объёма данных и прикручу многопоточность (сейчас сто волокон, но одна нить).
Кстати, монга скушала в два с половиной раза больше места на диске, чем ориент (монга хранит имена всех полей, а ориент не хранит имена полей, которые заданы в схеме), а ориент в 4 раза больше, чем постгрес (в постгресе не хранятся коллекции детей, вместо этого добавлен индекс по родителям — тут правда есть косяк, не сохраняется порядок комментариев).
Добавлю пару комментов в защиту монги:
--journalCommitInterval 2
Это видимо что-бы монга медленнее добавляла данные, а для надежности в реальных проектах просто делают реплику. А в orientdb и postgresql какой интервал сброса на диск (не в кеш ОС)?

Ну да ладно, речь про чтение,
а выборка связанных записей в постгресе в 2 раза быстрей, чем в монге и ориенте.
Потому что там та же выборка диапазона по индексу (что и в первом тесте). В монге можно сделать так же (doc.parent) и она будет такой же быстрой, т.е. монга дает варианты где у каждого свои плюсы, минусы. То же самое можно сделать и в orientdb, но он медленнее (судя по первому тесту), кстати в postgresql тоже можно запихнуть массив, в json*.
Это видимо что-бы монга медленнее добавляла данные, а для надежности в реальных проектах просто делают реплику.
Нет, это чтобы быть уверенным, что данные не потеряются. Реплика тут ничем не поможет (пример — нода отвечает, что сохранила и тут же падает, не успев реплицировать).

А в orientdb и postgresql какой интервал сброса на диск (не в кеш ОС)?
Без понятия, но увеличение его для монги погоды не делало.

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

кстати в postgresql тоже можно запихнуть массив, в json
Через костыль в виде hstore? Ну да, можно. Прелесть ориента в том, что можно иметь приемлемую скорость и хороший потенциал горизонтального масштабирования, не вывихивая себе мозг и не утапливая проект в грудах запутанного кода. Банально, в админке, чтобы перейти к связанной сущности достаточно кликнуть по ссылке, а не писать sql запрос — это значительно упрощает и ускоряет дебаг, так как связи между сущностями явные.
А, нет, postgres уверенными темпами движется в сторону монги :-) http://www.postgresql.org/docs/devel/static/datatype-json.html
В поле можно хранить json-документ, по нему можно даже некоторые индексы построить. Правда валидация идёт лесом, памяти больше ест и запросы похожи на перловые заклинания.
Реплика тут ничем не поможет (пример — нода отвечает, что сохранила и тут же падает, не успев реплицировать).
В монге как раз это продумано, вы при записи указываете сколько нод «запишет» ваш документ прежде чем вы получите ответ, например при w=2 — минимум две ноды получат документ прежде чем вы получите ответ о записи (при этом даже можно журналирование отключить).
А в случае с журналированием (что и в одиночном postgresql/orientdb) вы как раз имеете период когда данные еще не сбросились на диск.

И также придётся париться с сохранением порядка комментариев
Не для всех задач нужен порядок, (например комменты можно посортировать уже на клиенте), даже если добавить поле очередности комментов — оно все равно будет быстрее чем doc.child т.к. будет выборка одного диапазона из индекса (как в первом тесте).
Если не пугает перспектива потерять данные при обесточивании обеих нод, тогда проще in-memory базы поднять и к диску вообще не обращаться, кроме как для свопа и бэкапа ;-)

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

Ещё добавил графовое апи для ориента — оно раза в два медленнее при записи и при переходах по ссылкам.
Если не пугает перспектива потерять данные при обесточивании обеих нод
Шанс потерять данные при любом подходе есть, хоть и мизерный, что-бы снизить риск обесточивания «обеих» нод, их размещают в разных ДЦ.

На селектах, конечно, почти не отразилось.
Как я и предположил.

Я уже добавил постгресу отдельное поле для указания порядка — инсерты стали занимть по времени столько же, сколько и в ориенте
Вместо инкремента, который будет кривой в случае удаления комментов, можно писать timestamp, тогда будет быстро как в изначальном варианте (тем более поле «время» обычно есть у комментариев любого проекта).
Только вот дожидаться реплики из другого ДЦ придётся дольше, чем от сброса журнала на диск.

Временная метка ничем не лучше айдишника. Проблемы начинаются при переносах веток. Конкретно для комментов это не очень актуально, но обычно порядок элементов в списках всё же не зависит от времени создания этих элементов.
Только вот дожидаться реплики из другого ДЦ придётся дольше, чем от сброса журнала на диск.
Сейчас померял пинг из Амстердама (Digital Ocean) до Франкфурта (Leaseweb) = 1 — 1.5ms
ping
64 bytes from 185.28.68.36: icmp_seq=1 ttl=59 time=1.33 ms
64 bytes from 185.28.68.36: icmp_seq=2 ttl=59 time=1.10 ms
64 bytes from 185.28.68.36: icmp_seq=3 ttl=59 time=1.12 ms
64 bytes from 185.28.68.36: icmp_seq=4 ttl=59 time=1.09 ms
64 bytes from 185.28.68.36: icmp_seq=5 ttl=59 time=1.05 ms
64 bytes from 185.28.68.36: icmp_seq=6 ttl=59 time=1.23 ms

Даже если реплика для одиночной команды будет 10-20мс — это зачастую норм, зато общая производительность будет выше (для параллельных команд).

Кроме того монга дает возможность задавать «надежность записи» на каждую команду, неважные данные типа логов можно писать с w=0 без ожидания, что дает дополнительную скорость для клиента. Вообщем монга дает ассортимент в этом плане, регулятор между скоростью и надежностью.

Ну да ладно, сильно отклонились от сабжа, получается OrientDB медленнее в 2-5 раз, но ради удобства жертвовать скоростью иногда приемлемо (например использовать python вместо c++ для веба).
Конкретно мне понравились линки, ну и ребра (edge), вторые я не так часто использую, а линки не привносят столько удобств что-бы терять в скорости в 2+ раза. Конечно там ещё есть транзакции, но для веба обычно достаточно атомарных комитов (+ ради транзакций можно ещё пощупать другие решения).
Вообщем, OrientDB интересен, но для моих задач монга пока лучше.
Если данные не страшно потерять, то зачем их вообще писать? Логи ведь не просто так пишутся.

Возникает ощущение, что вы притворяетесь.

Разные данные имеют разную ценность, что, вроде, очевидно. Вы же не будете для хранения промежуточных данных, которые пересчитываются за час 5 дубликатов в 5 разных az/dc, если у вас допустима такая задержка (на пересчёт)?
У меня был проект, где не страшно было потерять сотню, другую из миллиарда, на итоговую статистику не влияло. Если писать без оповещения, это не значит что данные не запишутся, они пишутся так же как и с оповещением, а если монге плохо* то операция без оповещения выдаст ошибку. На практике проблем с этим нет.
Монга просто дает разные варианты (в отличие от других*), вы уже сами определяете что вам нужно.
Статистику можно собирать и не создавая миллиарды записей в базе. Я же говорил про те логи, которые помогают «расследовать происшествие», а не просто «массовка для статистики».

Я не сторонник половинчатых решений с неопределённым поведением. Если мне не важно записались ли данные, то я продолжу исполнение вообще не дожидаясь ответа от субд. Если же я дожидаюсь ответа, значит мне важно, прошла ли запись успешно, и если нет, то ожидаю получить информацию о произошедшей исключительной ситуации, какой бы она ни была. А не так, что «палка иногда стреляет, но редко и тихо».
Если мне не важно записались ли данные, то я продолжу исполнение вообще не дожидаясь ответа от субд. Если же я дожидаюсь ответа, значит мне важно, прошла ли запись успешно, и если нет, то ожидаю получить информацию о произошедшей исключительной ситуации, какой бы она ни была.
Вы как раз и описали работу с монгой, но у вас почему-то какая-то претензия.
Претензия у меня к тому, что по умолчанию монга торопится сказать, что записала, хотя по факту ещё нет. Но это исправимо настройками. А вот атомарность на уровне документа, а не всей базы — это уже не исправимо и приходится либо плясать вокруг двухфазных коммитов (что ещё в два раза замедлит её на запись), либо иметь ввиду, что данные в базе будут иногда разъезжаться.
Да, хорошо иметь банк данных, где будет и то, и это, и еще вон то. Да вот беда, кто бы не вводил эти данные, непременно сделает ошибку, да мало того, еще и специально напортит. Конечно, как ведь хорошо расположить базу деревом, вон файловая система и есть дерево — чем не база? В файловой системе есть еще и ссылки. Задание ответственному работнику: пойди ка, милай, проверь дерево базы данных со ссылками много ко многим на предмет соответствия реальному положению дел. Зачем нужна база данных, где сущности ветвятся себе как джунгли и только гуру-сталкер знает что где лежит, правда он уже пять лет на пенсии? Реляционные базы живы потому, что живой человек может контролировать данные в таблицах, и только в таблицах, и ни в чем, кроме таблиц — фамилия-адрес, фамилия-адрес. А всякие там ораклы путем весьма запутанных противоречивых алгоритмов пытаются такую уродливую форму хранения данных как то там обработать. Считается что конечному пользователю все должно быть просто и понятно, а программист пусть выкручивается как хочет — его проблемы ваще никого не волнуют. В базе все по прежнему — достоверность данных важнее всех остальных свойств вместе взятых.
Приплыли, как организовать структуру дерева в Cassandra? С утра порвался мозг. Спасибо за статью, как говорится. :)
К слову, с год назад SAP купил OrientDB (в составе CallidusCloud, купившего OrientDB перед тем).
Luca Garulli теперь вице-президент SAP. Минусовали, вероятно, завистники, которых SAP не купил :).
В 2019 году хорошо бы узнать как все сказанное автором в 2015 соотносится с архитектурой микросервисов. Связи на уровне хранилища там просто исчезают — хранилищ много, они распределенные (мое понимание).

"Распределенные" обычно имеет другое значение, чем тот тип хранилищ, что подразумевается в микросервисах по умолчанию. Система распределённой становится, но хранилища у каждого сервиса "локальные". И связи внутри них он контролирует, типа не должно быть "висящих" OrderLine без соответствующего Order в сервисе заказов. А что в сервисе контрагентов для Order.customerId не найдётся записи не его ответственность, а зачастую и ошибкой не считается. Необходимость ссылочной целостности зачастую преувеличена.

Да конечно «рапределенное хранилище» не самое удачное название потому что термин уже занят, но что имелось ввиду понятно. Так а вы подтверждаете что реализация ссылочная в стиле OrientDB так же неактуальна как и ссыслочная целостность в стиле RDBMS (для микросервисов)? Это примерно то что я хотел сказать (но с приставкой «кажется», потому что эту собаку не ел).

Боюсь, я недостаточно игрался с OrientDB, чтобы понимать о чём речь. Но в целом в мире MSA связь сущностей разных сервисов осуществляется по идентификаторам и целостность этих ссылок в произвольный момент времени не подразумевается. Даже стремление к ней не подразумевается, если этого нет в требованиях.

Что за непонятные числа?
select expand( friend ) from #19:0

Articles